text: // Copyright (c) Microsoft. All rights reserved.
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  
  #ifdef __cplusplus
  #include <cstdio>
  #include <cstdlib>
  #include <cstddef>
  #include <ctime>
  #else
  #include <stdio.h>
  #include <stdlib.h>
  #include <stddef.h>
  #include <stdbool.h>
  #include <time.h>
  #endif
  
  #if defined _MSC_VER
  #pragma warning(disable: 4054) /* MSC incorrectly fires this */
  #endif
  
  void* real_malloc(size_t size)
  {
      return malloc(size);
  }
  
  void real_free(void* ptr)
  {
      free(ptr);
  }
  
  #include "testrunnerswitcher.h"
  #include "azure_c_shared_utility/optimize_size.h"
  #include "azure_macro_utils/macro_utils.h"
  #include "azure_c_shared_utility/shared_util_options.h"
  #include "umock_c/umock_c.h"
  #include "umock_c/umocktypes_charptr.h"
  #include "umock_c/umocktypes_stdint.h"
  #include "umock_c/umocktypes_bool.h"
  #include "umock_c/umock_c_negative_tests.h"
  #include "umock_c/umocktypes.h"
  #include "umock_c/umocktypes_c.h"
  
  #ifdef __cplusplus
  extern "C"
  {
  #endif
      static int saved_malloc_returns_count = 0;
      static void* saved_malloc_returns[20];
  
      static void* TEST_malloc(size_t size)
      {
          saved_malloc_returns[saved_malloc_returns_count] = real_malloc(size);
  
          return saved_malloc_returns[saved_malloc_returns_count++];
      }
  
      static void TEST_free(void* ptr)
      {
          int i, j;
          for (i = 0, j = 0; j < saved_malloc_returns_count; i++, j++)
          {
              if (saved_malloc_returns[i] == ptr)
              {
                  real_free(ptr);
                  j++;
              }
  
              saved_malloc_returns[i] = saved_malloc_returns[j];
          }
  
          if (i != j) saved_malloc_returns_count--;
      }
  
      static int TEST_mallocAndStrcpy_s_return;
      static int TEST_mallocAndStrcpy_s(char** destination, const char* source)
      {
          *destination = (char*)source;
          return TEST_mallocAndStrcpy_s_return;
      }
  
      void* my_gballoc_realloc(void* ptr, size_t size)
      {
          return realloc(ptr, size);
      }
  
  #ifdef __cplusplus
  }
  #endif
  
  
  #define ENABLE_MOCKS
  #include "azure_c_shared_utility/gballoc.h"
  #include "azure_c_shared_utility/singlylinkedlist.h"
  #include "azure_c_shared_utility/doublylinkedlist.h"
  #include "azure_c_shared_utility/platform.h"
  #include "azure_c_shared_utility/strings.h"
  #include "azure_c_shared_utility/urlencode.h"
  #include "azure_c_shared_utility/tlsio.h"
  #include "azure_c_shared_utility/agenttime.h"
  #include "azure_c_shared_utility/crt_abstractions.h"
  #include "azure_c_shared_utility/optionhandler.h"
  #include "azure_c_shared_utility/socketio.h"
  
  #include "azure_uamqp_c/cbs.h"
  #include "azure_uamqp_c/amqpvalue.h"
  
  #include "iothub_client_core_ll.h"
  #include "iothub_client_options.h"
  #include "internal/iothub_client_private.h"
  #include "iothub_client_version.h"
  #include "internal/iothub_client_retry_control.h"
  #include "internal/iothubtransportamqp_methods.h"
  #include "internal/iothubtransport_amqp_connection.h"
  #include "internal/iothubtransport_amqp_device.h"
  
  #include "internal/iothub_transport_ll_private.h"
  
  MOCKABLE_FUNCTION(, bool, Transport_MessageCallbackFromInput, MESSAGE_CALLBACK_INFO*, messageData, void*, ctx);
  MOCKABLE_FUNCTION(, bool, Transport_MessageCallback, MESSAGE_CALLBACK_INFO*, messageData, void*, ctx);
  MOCKABLE_FUNCTION(, void, Transport_ConnectionStatusCallBack, IOTHUB_CLIENT_CONNECTION_STATUS, status, IOTHUB_CLIENT_CONNECTION_STATUS_REASON, reason, void*, ctx);
  MOCKABLE_FUNCTION(, void, Transport_SendComplete_Callback, PDLIST_ENTRY, completed, IOTHUB_CLIENT_CONFIRMATION_RESULT, result, void*, ctx);
  MOCKABLE_FUNCTION(, const char*, Transport_GetOption_Product_Info_Callback, void*, ctx);
  MOCKABLE_FUNCTION(, void, Transport_Twin_ReportedStateComplete_Callback, uint32_t, item_id, int, status_code, void*, ctx);
  MOCKABLE_FUNCTION(, void, Transport_Twin_RetrievePropertyComplete_Callback, DEVICE_TWIN_UPDATE_STATE, update_state, const unsigned char*, payLoad, size_t, size, void*, ctx);
  MOCKABLE_FUNCTION(, int, Transport_DeviceMethod_Complete_Callback, const char*, method_name, const unsigned char*, payLoad, size_t, size, METHOD_HANDLE, response_id, void*, ctx);
  
  #undef ENABLE_MOCKS
  
  #include "internal/iothubtransport_amqp_common.h"
  
  TEST_DEFINE_ENUM_TYPE(AMQP_CONNECTION_STATE, AMQP_CONNECTION_STATE_VALUES);
  IMPLEMENT_UMOCK_C_ENUM_TYPE(AMQP_CONNECTION_STATE, AMQP_CONNECTION_STATE_VALUES);
  
  TEST_DEFINE_ENUM_TYPE(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUES);
  IMPLEMENT_UMOCK_C_ENUM_TYPE(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUES);
  
  MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(AMQP_CONNECTION_STATE, AMQP_CONNECTION_STATE_VALUES);
  
  static bool g_failDispositionMake;
  static bool g_failDispositionSend;
  
  #ifdef __cplusplus
  extern "C"
  {
  #endif
  
      extern int real_DList_RemoveEntryList(PDLIST_ENTRY Entry);
      extern void real_DList_InsertTailList(PDLIST_ENTRY ListHead, PDLIST_ENTRY Entry);
      extern int real_DList_IsListEmpty(const PDLIST_ENTRY ListHead);
      extern void real_DList_InitializeListHead(PDLIST_ENTRY ListHead);
  
      int my_DList_RemoveEntryList(PDLIST_ENTRY Entry)
      {
          return real_DList_RemoveEntryList(Entry);
      }
  
      void my_DList_InsertTailList(PDLIST_ENTRY ListHead, PDLIST_ENTRY Entry)
      {
          real_DList_InsertTailList(ListHead, Entry);
      }
  
      int my_DList_IsListEmpty(const PDLIST_ENTRY ListHead)
      {
          return real_DList_IsListEmpty(ListHead);
      }
  
      void my_DList_InitializeListHead(PDLIST_ENTRY ListHead)
      {
          real_DList_InitializeListHead(ListHead);
      }
  
  
      // singlylinkedlist
      static int saved_registered_devices_list_count;
      static const void* saved_registered_devices_list[20];
  
      static bool TEST_singlylinkedlist_add_fail_return = false;
      static LIST_ITEM_HANDLE TEST_singlylinkedlist_add(SINGLYLINKEDLIST_HANDLE list, const void* item)
      {
          (void)list;
          saved_registered_devices_list[saved_registered_devices_list_count++] = item;
  
          return TEST_singlylinkedlist_add_fail_return ? NULL : (LIST_ITEM_HANDLE)item;
      }
  
      static int TEST_singlylinkedlist_remove_return = 0;
      static int TEST_singlylinkedlist_remove(SINGLYLINKEDLIST_HANDLE list, LIST_ITEM_HANDLE item)
      {
          (void)list;
          const void** TEST_list = NULL;
          int* TEST_list_count = NULL;
  
          TEST_list = saved_registered_devices_list;
          TEST_list_count = &saved_registered_devices_list_count;
  
          int i;
          int item_found = 0;
          for (i = 0; i < *TEST_list_count; i++)
          {
              if (item_found)
              {
                  TEST_list[i - 1] = TEST_list[i];
              }
              else if (TEST_list[i] == item)
              {
                  item_found = 1;
              }
          }
  
          if (item_found)
          {
              (*TEST_list_count)--;
          }
  
          return item_found == 1 ? 0 : 1;
      }
  
      static LIST_ITEM_HANDLE TEST_singlylinkedlist_find(SINGLYLINKEDLIST_HANDLE list, LIST_MATCH_FUNCTION match_function, const void* match_context)
      {
          (void)list;
          (void)match_function;
          return (LIST_ITEM_HANDLE)match_context;
      }
  
      static SINGLYLINKEDLIST_HANDLE TEST_singlylinkedlist_foreach_list;
      static LIST_ACTION_FUNCTION TEST_singlylinkedlist_foreach_action_function;
      static const void* TEST_singlylinkedlist_foreach_context;
      static int TEST_singlylinkedlist_foreach(SINGLYLINKEDLIST_HANDLE list, LIST_ACTION_FUNCTION action_function, const void* action_context)
      {
          TEST_singlylinkedlist_foreach_list = list;
          TEST_singlylinkedlist_foreach_action_function = action_function;
          TEST_singlylinkedlist_foreach_context = action_context;
          return 0;
      }
  
      static const void* TEST_singlylinkedlist_item_get_value(LIST_ITEM_HANDLE item_handle)
      {
          return (const void*)item_handle;
      }
  
      static LIST_ITEM_HANDLE TEST_singlylinkedlist_get_head_item(SINGLYLINKEDLIST_HANDLE list)
      {
          (void)list;
          LIST_ITEM_HANDLE list_item;
  
          if (saved_registered_devices_list_count <= 0)
          {
              list_item = NULL;
          }
          else
          {
              list_item = (LIST_ITEM_HANDLE)saved_registered_devices_list[0];
          }
  
          return list_item;
      }
  
      static LIST_ITEM_HANDLE TEST_singlylinkedlist_get_next_item(LIST_ITEM_HANDLE item_handle)
      {
          LIST_ITEM_HANDLE next_item = NULL;
  
          int i;
          int item_found = 0;
          for (i = 0; i < saved_registered_devices_list_count; i++)
          {
              if (item_found)
              {
                  next_item = (LIST_ITEM_HANDLE)saved_registered_devices_list[i];
                  break;
              }
              else if (saved_registered_devices_list[i] == (void*)item_handle)
              {
                  item_found = 1;
              }
          }
  
          return next_item;
      }
  
  
      static int g_STRING_sprintf_call_count;
      static int g_STRING_sprintf_fail_on_count;
      static STRING_HANDLE saved_STRING_sprintf_handle;
  
      int STRING_sprintf(STRING_HANDLE handle, const char* format, ...)
      {
          int result;
          saved_STRING_sprintf_handle = handle;
          (void)format;
  
          g_STRING_sprintf_call_count++;
  
          if (g_STRING_sprintf_call_count == g_STRING_sprintf_fail_on_count)
          {
              result = __LINE__;
          }
          else
          {
              result = 0;
          }
  
          return result;
      }
  
      static STRING_HANDLE STRING_construct_sprintf_result;
      STRING_HANDLE STRING_construct_sprintf(const char* format, ...)
      {
          (void)format;
          return STRING_construct_sprintf_result;
      }
  
      static ON_DEVICE_C2D_MESSAGE_RECEIVED TEST_device_subscribe_message_saved_callback;
      static void* TEST_device_subscribe_message_saved_context;
      static int TEST_device_subscribe_message_return;
      static int TEST_device_subscribe_message(AMQP_DEVICE_HANDLE handle, ON_DEVICE_C2D_MESSAGE_RECEIVED on_message_received_callback, void* context)
      {
          (void)handle;
          TEST_device_subscribe_message_saved_callback = on_message_received_callback;
          TEST_device_subscribe_message_saved_context = context;
          return TEST_device_subscribe_message_return;
      }
  
      static IOTHUB_CLIENT_RESULT TEST_IoTHubClientCore_LL_GetOption(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* optionName, void** value)
      {
          (void)iotHubClientHandle;
          (void)optionName;
  
          *value = (STRING_HANDLE)0x87;
          return IOTHUB_CLIENT_OK;
      }
  
  #ifdef __cplusplus
  }
  #endif
  
  MOCKABLE_FUNCTION(, time_t, get_time, time_t*, currentTime);
  MOCKABLE_FUNCTION(, double, get_difftime, time_t, stopTime, time_t, startTime);
  
  
  typedef struct DEVICE_DATA_TAG
  {
      AMQP_DEVICE_HANDLE device_handle;
  } DEVICE_DATA;
  
  
  static DEVICE_DATA g_device_state;
  
  
  typedef struct MESSAGE_DISPOSITION_CONTEXT_TAG
  {
      DEVICE_DATA* device_state;
      char* link_name;
      uint32_t message_id;
  } MESSAGE_DISPOSITION_CONTEXT;
  
  
  static TEST_MUTEX_HANDLE g_testByTest;
  
  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)
  {
      char temp_str[256];
      (void)snprintf(temp_str, sizeof(temp_str), "umock_c reported error :%s", MU_ENUM_TO_STRING(UMOCK_C_ERROR_CODE, error_code));
      ASSERT_FAIL(temp_str);
  }
  
  
  // ---------- Control parameters ---------- //
  
  #define INDEFINITE_TIME                            ((time_t)-1)
  #define TEST_DEVICE_ID_CHAR_PTR                    "deviceid"
  #define TEST_PRODUCT_INFO_CHAR_PTR                 "product info"
  #define TEST_DEVICE_ID_2_CHAR_PTR                  "deviceid2"
  #define TEST_DEVICE_KEY                            "devicekey"
  #define TEST_DEVICE_SAS_TOKEN                      "deviceSas"
  #define TEST_IOT_HUB_NAME                          "servername"
  #define TEST_IOT_HUB_SUFFIX                        "domainname"
  #define TEST_IOT_HUB_PORT                          5671
  #define TEST_PROT_GW_HOSTNAME_NULL                 NULL
  #define TEST_PROT_GW_HOSTNAME                      "gw"
  #define TEST_DEVICE_STATUS_CODE                    200
  #define TEST_DEFAULT_SVC2CL_KEEP_ALIVE_FREQ_SECS   240
  #define TEST_USER_SVC2CL_KEEP_ALIVE_FREQ_SECS      123
  #define TEST_DEFAULT_REMOTE_IDLE_TIMEOUT_RATIO     0.50
  #define TEST_USER_REMOTE_IDLE_TIMEOUT_RATIO        0.875
  #define DEFAULT_RETRY_POLICY                      IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER
  #define DEFAULT_MAX_RETRY_TIME_IN_SECS            0
  
  #define TEST_STRING_HANDLE                         (STRING_HANDLE)0x4240
  #define TEST_IOTHUBTRANSPORTAMQP_METHODS           ((IOTHUBTRANSPORT_AMQP_METHODS_HANDLE)0x4244)
  #define TEST_SESSION_HANDLE                        ((SESSION_HANDLE)0x4245)
  #define TEST_METHOD_HANDLE                         ((IOTHUBTRANSPORT_AMQP_METHOD_HANDLE)0x4246)
  #define TEST_XIO_INTERFACE                         ((const IO_INTERFACE_DESCRIPTION*)0x4247)
  #define TEST_XIO_HANDLE                            ((XIO_HANDLE)0x4248)
  #define TEST_SASL_MECHANISM                        ((SASL_MECHANISM_HANDLE)0x4249)
  #define TEST_SASL_MSSBCBS_INTERFACE                ((const SASL_MECHANISM_INTERFACE_DESCRIPTION*)0x4250)
  #define TEST_CONNECTION_HANDLE                     ((CONNECTION_HANDLE)0x4251)
  #define TEST_CBS_HANDLE                            ((CBS_HANDLE)0x4253)
  #define TEST_MESSAGING_SOURCE                      ((AMQP_VALUE)0x4254)
  #define TEST_MESSAGING_TARGET                      ((AMQP_VALUE)0x4255)
  #define TEST_BUFFER_HANDLE                         ((BUFFER_HANDLE)0x4256)
  #define TEST_AMQP_MAP                              ((AMQP_VALUE)0x4258)
  #define TEST_AMQP_VALUE                            ((AMQP_VALUE)0x4260)
  
  #define TEST_UNDERLYING_IO_TRANSPORT               ((XIO_HANDLE)0x4261)
  #define TEST_TRANSPORT_PROVIDER                    ((TRANSPORT_PROVIDER*)0x4263)
  #define TEST_IOTHUB_HOST_FQDN_CHAR_PTR             "servername.domainname"
  #define TEST_IOTHUB_HOST_FQDN_STRING_HANDLE        (STRING_HANDLE)0x4264
  #define TEST_IOTHUB_HOST_FQDN_CLONE_STRING_HANDLE  (STRING_HANDLE)0x4265
  #define TEST_PROTOCOL_PROVIDER                     (IOTHUB_CLIENT_TRANSPORT_PROVIDER)0x4266
  #define TEST_REGISTERED_DEVICES_LIST               (SINGLYLINKEDLIST_HANDLE)0x4267
  #define TEST_DEVICE_ID_STRING_HANDLE               (STRING_HANDLE)0x4268
  #define TEST_DEVICE_HANDLE                         (AMQP_DEVICE_HANDLE)0x4269
  #define TEST_LIST_ITEM_HANDLE                      (LIST_ITEM_HANDLE)0x4270
  #define TEST_AMQP_CONNECTION_HANDLE                (AMQP_CONNECTION_HANDLE)0x4271
  #define TEST_IOTHUB_MESSAGE_LIST_HANDLE            (IOTHUB_MESSAGE_LIST*)0x4272
  #define TEST_IOTHUB_DEVICE_HANDLE                  (IOTHUB_DEVICE_HANDLE)0x4273
  #define TEST_OPTIONHANDLER_HANDLE                  (OPTIONHANDLER_HANDLE)0x4274
  #define TEST_IOTHUB_MESSAGE_HANDLE                 (IOTHUB_MESSAGE_HANDLE)0x4275
  #define TEST_X509_CERTIFICATE                      "Ariano Suassuna"
  #define TEST_X509_PRIVATE_KEY                      "Raphael Rabello"
  #define TEST_MESSAGE_SOURCE_CHAR_PTR               "messagereceiver_link_name"
  #define TEST_RETRY_CONTROL_HANDLE                  (RETRY_CONTROL_HANDLE)0x4276
  
  static TRANSPORT_CALLBACKS_INFO transport_cb_info;
  static void* transport_cb_ctx = (void*)0x499922;
  
  static const unsigned char* TEST_DEVICE_METHOD_RESPONSE = (const unsigned char*)0x62;
  static size_t TEST_DEVICE_RESP_LENGTH = 1;
  
  static const IOTHUB_CLIENT_CORE_LL_HANDLE TEST_IOTHUB_CLIENT_CORE_LL_HANDLE = (IOTHUB_CLIENT_CORE_LL_HANDLE)0x4343;
  
  static time_t TEST_current_time;
  static DLIST_ENTRY TEST_waitingToSend;
  
  static unsigned long TEST_MESSAGE_ID;
  
  
  // ---------- Helpers for Expected Calls ---------- //
  
  // @remarks
  //     IHTAC = IoTHubTransport_AMQP_Common
  static void set_expected_calls_for_Create(IOTHUBTRANSPORT_CONFIG* transport_config)
  {
      STRICT_EXPECTED_CALL(IoTHub_Transport_ValidateCallbacks(IGNORED_PTR_ARG) );
      EXPECTED_CALL(malloc(IGNORED_NUM_ARG));
  
      STRICT_EXPECTED_CALL(retry_control_create(DEFAULT_RETRY_POLICY, DEFAULT_MAX_RETRY_TIME_IN_SECS));
  
      if (transport_config->upperConfig->protocolGatewayHostName != NULL)
      {
          STRICT_EXPECTED_CALL(STRING_construct(transport_config->upperConfig->protocolGatewayHostName))
              .SetReturn(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE);
      }
      else if (transport_config->upperConfig->iotHubName != NULL)
      {
          STRING_construct_sprintf_result = TEST_IOTHUB_HOST_FQDN_STRING_HANDLE;
      }
  
      STRICT_EXPECTED_CALL(singlylinkedlist_create())
          .SetReturn(TEST_REGISTERED_DEVICES_LIST);
  }
  
  static void set_expected_calls_for_GetSendStatus(bool is_waiting_to_send_list_empty, DEVICE_SEND_STATUS send_status)
  {
      if (!is_waiting_to_send_list_empty)
      {
          STRICT_EXPECTED_CALL(DList_IsListEmpty(IGNORED_PTR_ARG))
              .SetReturn(0)
              .CallCannotFail();
      }
      else
      {
          STRICT_EXPECTED_CALL(DList_IsListEmpty(IGNORED_PTR_ARG))
              .SetReturn(1)
              .CallCannotFail();
          STRICT_EXPECTED_CALL(amqp_device_get_send_status(TEST_DEVICE_HANDLE, IGNORED_PTR_ARG))
              .IgnoreArgument(2)
              .CopyOutArgumentBuffer(2, &send_status, sizeof(DEVICE_SEND_STATUS))
              .SetReturn(0);
      }
  }
  
  static void set_expected_calls_for_GetHostname()
  {
      STRICT_EXPECTED_CALL(STRING_clone(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE)).SetReturn(TEST_IOTHUB_HOST_FQDN_CLONE_STRING_HANDLE);
  }
  
  static void set_expected_calls_for_is_device_registered_ex(IOTHUB_DEVICE_CONFIG* device_config, IOTHUB_DEVICE_HANDLE registered_device)
  {
      (void)device_config;
  
      STRICT_EXPECTED_CALL(singlylinkedlist_find(TEST_REGISTERED_DEVICES_LIST, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
          .SetReturn((LIST_ITEM_HANDLE)registered_device).CallCannotFail();
  }
  
  static MESSAGE_DISPOSITION_CONTEXT* TRANSPORT_CONTEXT_DATA_create2(IOTHUB_DEVICE_HANDLE device_handle)
  {
      MESSAGE_DISPOSITION_CONTEXT* result = (MESSAGE_DISPOSITION_CONTEXT*)malloc(sizeof(MESSAGE_DISPOSITION_CONTEXT));
      memset(result, 0, sizeof(MESSAGE_DISPOSITION_CONTEXT));
      result->link_name = (char*)malloc(12);
      sprintf(result->link_name, "my_link");
      result->device_state = (DEVICE_DATA*)device_handle;
      return result;
  }
  
  static void set_expected_calls_for_create_device_message_disposition_info()
  {
      STRICT_EXPECTED_CALL(malloc(sizeof(DEVICE_MESSAGE_DISPOSITION_INFO)));
  
      static char* source = TEST_MESSAGE_SOURCE_CHAR_PTR;
      EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, IGNORED_PTR_ARG))
          .CopyOutArgumentBuffer_destination(&source, sizeof(char*));
  }
  
  static void set_expected_calls_for_destroy_device_message_disposition_info()
  {
      EXPECTED_CALL(free(IGNORED_PTR_ARG));
      EXPECTED_CALL(free(IGNORED_PTR_ARG));
  }
  
  static void set_expected_calls_for_SendMessageDisposition(IOTHUBMESSAGE_DISPOSITION_RESULT iothc_disposition_result)
  {
      DEVICE_MESSAGE_DISPOSITION_RESULT device_disposition_result;
  
      if (iothc_disposition_result == IOTHUBMESSAGE_ACCEPTED)
      {
          device_disposition_result = DEVICE_MESSAGE_DISPOSITION_RESULT_ACCEPTED;
      }
      else if (iothc_disposition_result == IOTHUBMESSAGE_ABANDONED)
      {
          device_disposition_result = DEVICE_MESSAGE_DISPOSITION_RESULT_RELEASED;
      }
      else if (iothc_disposition_result == IOTHUBMESSAGE_REJECTED)
      {
          device_disposition_result = DEVICE_MESSAGE_DISPOSITION_RESULT_REJECTED;
      }
      else // unexpected.
      {
          device_disposition_result = DEVICE_MESSAGE_DISPOSITION_RESULT_NONE;
      }
  
      set_expected_calls_for_create_device_message_disposition_info();
      STRICT_EXPECTED_CALL(amqp_device_send_message_disposition(TEST_DEVICE_HANDLE, IGNORED_PTR_ARG, device_disposition_result))
          .IgnoreArgument(2);
  
      STRICT_EXPECTED_CALL(IoTHubMessage_Destroy(IGNORED_PTR_ARG)).IgnoreArgument_iotHubMessageHandle();
  
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG)).IgnoreArgument_ptr();
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG)).IgnoreArgument_ptr();
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG)).IgnoreArgument_ptr();
  
      set_expected_calls_for_destroy_device_message_disposition_info();
  }
  
  // @param registered_device
  //     provide the handle to the registered device if the expected call is supposed to return an item,
  //     or NULL if the intent is to return "not registered".
  static void set_expected_calls_for_is_device_registered(IOTHUB_DEVICE_CONFIG* device_config, IOTHUB_DEVICE_HANDLE registered_device)
  {
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_DEVICE_ID_STRING_HANDLE))
          .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
  
      set_expected_calls_for_is_device_registered_ex(device_config, registered_device);
  }
  
  static void set_expected_calls_for_Register(IOTHUB_DEVICE_CONFIG* device_config, bool is_using_cbs)
  {
      set_expected_calls_for_is_device_registered_ex(device_config, NULL);
  
      // is_device_credential_acceptable
      // Nothing to expect.
  
      EXPECTED_CALL(malloc(IGNORED_NUM_ARG));
      STRICT_EXPECTED_CALL(STRING_construct(device_config->deviceId))
          .SetReturn(TEST_DEVICE_ID_STRING_HANDLE);
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE))
          .SetReturn(TEST_IOTHUB_HOST_FQDN_CHAR_PTR).CallCannotFail();
      EXPECTED_CALL(amqp_device_create(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(TEST_REGISTERED_DEVICES_LIST))
          .SetReturn(NULL).CallCannotFail();
  
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE)).SetReturn(TEST_IOTHUB_HOST_FQDN_CHAR_PTR).CallCannotFail();
      EXPECTED_CALL(iothubtransportamqp_methods_create(TEST_IOTHUB_HOST_FQDN_CHAR_PTR, device_config->deviceId, NULL));
  
      // replicate_device_options_to
      STRICT_EXPECTED_CALL(amqp_device_set_option(TEST_DEVICE_HANDLE, DEVICE_OPTION_EVENT_SEND_TIMEOUT_SECS, IGNORED_PTR_ARG));
  
      if (is_using_cbs)
      {
          STRICT_EXPECTED_CALL(amqp_device_set_option(TEST_DEVICE_HANDLE, DEVICE_OPTION_CBS_REQUEST_TIMEOUT_SECS, IGNORED_PTR_ARG));
      }
  
      STRICT_EXPECTED_CALL(singlylinkedlist_add(TEST_REGISTERED_DEVICES_LIST, IGNORED_PTR_ARG));
  }
  
  static void set_expected_calls_for_Unregister(IOTHUB_DEVICE_HANDLE iothub_device_handle)
  {
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_DEVICE_ID_STRING_HANDLE))
          .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
  
      STRICT_EXPECTED_CALL(singlylinkedlist_find(TEST_REGISTERED_DEVICES_LIST, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
          .IgnoreArgument(2)
          .IgnoreArgument(3)
          .SetReturn((LIST_ITEM_HANDLE)iothub_device_handle);
  
      STRICT_EXPECTED_CALL(singlylinkedlist_remove(TEST_REGISTERED_DEVICES_LIST, IGNORED_PTR_ARG))
          .IgnoreArgument(2);
  
      STRICT_EXPECTED_CALL(iothubtransportamqp_methods_destroy(TEST_IOTHUBTRANSPORTAMQP_METHODS));
  
      STRICT_EXPECTED_CALL(amqp_device_destroy(TEST_DEVICE_HANDLE));
      STRICT_EXPECTED_CALL(STRING_delete(TEST_DEVICE_ID_STRING_HANDLE));
      EXPECTED_CALL(free(IGNORED_PTR_ARG));
  }
  
  static void set_expected_calls_for_establish_amqp_connection()
  {
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE))
          .SetReturn(TEST_IOTHUB_HOST_FQDN_CHAR_PTR);
      EXPECTED_CALL(amqp_connection_create(IGNORED_PTR_ARG));
  }
  
  static void set_expected_calls_for_subscribe_methods()
  {
      STRICT_EXPECTED_CALL(amqp_connection_get_session_handle(TEST_AMQP_CONNECTION_HANDLE, IGNORED_PTR_ARG))
          .IgnoreArgument_session_handle();
  
      STRICT_EXPECTED_CALL(iothubtransportamqp_methods_subscribe(TEST_IOTHUBTRANSPORTAMQP_METHODS, TEST_SESSION_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
          .IgnoreArgument_on_methods_error()
          .IgnoreArgument_on_methods_error_context()
          .IgnoreArgument_on_method_request_received()
          .IgnoreArgument_on_method_request_received_context()
          .IgnoreArgument_on_methods_unsubscribed()
          .IgnoreArgument_on_methods_unsubscribed_context();
  }
  
  static void set_expected_calls_for_on_methods_unsubscribed()
  {
      STRICT_EXPECTED_CALL(iothubtransportamqp_methods_unsubscribe(TEST_IOTHUBTRANSPORTAMQP_METHODS));
  }
  
  static void set_expected_calls_for_send_pending_events(PDLIST_ENTRY wts, int expected_number_of_events)
  {
      int i;
      for (i = 0; i < expected_number_of_events; i++)
      {
          STRICT_EXPECTED_CALL(DList_IsListEmpty(wts));
          EXPECTED_CALL(DList_RemoveEntryList(IGNORED_PTR_ARG));
  
          STRICT_EXPECTED_CALL(amqp_device_send_event_async(TEST_DEVICE_HANDLE, TEST_IOTHUB_MESSAGE_LIST_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
              .IgnoreArgument(3)
              .IgnoreArgument(4);
      }
  
      STRICT_EXPECTED_CALL(DList_IsListEmpty(wts))
          .SetReturn(1);
  }
  
  static void set_expected_calls_for_Device_DoWork(PDLIST_ENTRY wts, int wts_length, DEVICE_STATE current_device_state, bool is_using_cbs, time_t current_time, bool subscribe_for_methods)
  {
      if (current_device_state == DEVICE_STATE_STOPPED)
      {
          STRICT_EXPECTED_CALL(amqp_connection_get_session_handle(TEST_AMQP_CONNECTION_HANDLE, IGNORED_PTR_ARG))
              .IgnoreArgument_session_handle();
  
          if (is_using_cbs)
          {
              STRICT_EXPECTED_CALL(amqp_connection_get_cbs_handle(TEST_AMQP_CONNECTION_HANDLE, IGNORED_PTR_ARG))
                  .IgnoreArgument_cbs_handle();
  
              STRICT_EXPECTED_CALL(amqp_device_start_async(TEST_DEVICE_HANDLE, TEST_SESSION_HANDLE, TEST_CBS_HANDLE));
          }
          else
          {
              STRICT_EXPECTED_CALL(amqp_device_start_async(TEST_DEVICE_HANDLE, TEST_SESSION_HANDLE, IGNORED_PTR_ARG));
          }
      }
      else if (current_device_state == DEVICE_STATE_STARTING ||
          current_device_state == DEVICE_STATE_STOPPING)
      {
          // is_timeout_reached
          STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(current_time);
          EXPECTED_CALL(get_difftime(IGNORED_NUM_ARG, IGNORED_NUM_ARG));
      }
      else if (current_device_state == DEVICE_STATE_ERROR_AUTH || current_device_state == DEVICE_STATE_ERROR_MSG)
      {
          STRICT_EXPECTED_CALL(STRING_c_str(TEST_DEVICE_ID_STRING_HANDLE))
              .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
  
          STRICT_EXPECTED_CALL(amqp_device_stop(TEST_DEVICE_HANDLE));
      }
      else if (current_device_state == DEVICE_STATE_STARTED)
      {
          if (subscribe_for_methods)
          {
              set_expected_calls_for_subscribe_methods();
          }
  
          set_expected_calls_for_send_pending_events(wts, wts_length);
      }
  
      STRICT_EXPECTED_CALL(amqp_device_do_work(TEST_DEVICE_HANDLE));
  }
  
  static void set_expected_calls_for_get_new_underlying_io_transport(bool feed_options)
  {
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE))
          .SetReturn(TEST_IOTHUB_HOST_FQDN_CHAR_PTR);
      //STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_Credential_Type(IGNORED_PTR_ARG));
  
      if (feed_options)
      {
          STRICT_EXPECTED_CALL(OptionHandler_FeedOptions(TEST_OPTIONHANDLER_HANDLE, TEST_UNDERLYING_IO_TRANSPORT))
              .SetReturn(OPTIONHANDLER_OK);
      }
  }
  
  static void set_expected_calls_for_DoWork2(PDLIST_ENTRY wts, int wts_length, DEVICE_STATE current_device_state, bool is_tls_io_acquired, bool feed_options, bool is_using_cbs, bool is_connection_created, bool is_connection_open, int number_of_registered_devices, time_t current_time, bool subscribe_for_methods)
  {
      STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(TEST_REGISTERED_DEVICES_LIST));
  
      if (!is_tls_io_acquired)
      {
          set_expected_calls_for_get_new_underlying_io_transport(feed_options);
      }
  
      if (!is_connection_created)
      {
          set_expected_calls_for_establish_amqp_connection();
  
          is_connection_created = true;
      }
  
      if (is_connection_open)
      {
          int i;
          for (i = 0; i < number_of_registered_devices; i++)
          {
              EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG));
              set_expected_calls_for_Device_DoWork(wts, wts_length, current_device_state, is_using_cbs, current_time, subscribe_for_methods);
              EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG));
          }
      }
  
      if (is_connection_created)
      {
          STRICT_EXPECTED_CALL(amqp_connection_do_work(TEST_AMQP_CONNECTION_HANDLE));
      }
  }
  
  static void set_expected_calls_for_DoWork(PDLIST_ENTRY wts, int wts_length, DEVICE_STATE current_device_state, bool is_tls_io_acquired, bool is_using_cbs, bool is_connection_created, bool is_connection_open, int number_of_registered_devices, time_t current_time, bool subscribe_for_methods)
  {
      set_expected_calls_for_DoWork2(wts, wts_length, current_device_state, is_tls_io_acquired, false /* feed_options */, is_using_cbs, is_connection_created, is_connection_open, number_of_registered_devices, current_time, subscribe_for_methods);
  }
  
  static void set_expected_calls_for_Destroy(int number_of_registered_devices, IOTHUB_DEVICE_HANDLE* registered_devices)
  {
      STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(TEST_REGISTERED_DEVICES_LIST));
  
      int i;
      for (i = 0; i < number_of_registered_devices; i++)
      {
          EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG));
          EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG));
          set_expected_calls_for_Unregister(registered_devices[i]);
      }
  
      STRICT_EXPECTED_CALL(singlylinkedlist_destroy(TEST_REGISTERED_DEVICES_LIST));
      STRICT_EXPECTED_CALL(amqp_connection_destroy(TEST_AMQP_CONNECTION_HANDLE));
      STRICT_EXPECTED_CALL(xio_destroy(TEST_UNDERLYING_IO_TRANSPORT));
      STRICT_EXPECTED_CALL(retry_control_destroy(TEST_RETRY_CONTROL_HANDLE));
      STRICT_EXPECTED_CALL(STRING_delete(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE));
      EXPECTED_CALL(free(IGNORED_PTR_ARG));
  }
  
  static void set_expected_calls_for_Subscribe(IOTHUB_DEVICE_CONFIG* device_config, IOTHUB_DEVICE_HANDLE registered_device)
  {
      set_expected_calls_for_is_device_registered(device_config, registered_device);
  
      STRICT_EXPECTED_CALL(amqp_device_subscribe_message(TEST_DEVICE_HANDLE, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
          .IgnoreArgument(2)
          .IgnoreArgument(3);
  }
  
  static void set_expected_calls_for_Unsubscribe(IOTHUB_DEVICE_CONFIG* device_config, IOTHUB_DEVICE_HANDLE registered_device)
  {
      set_expected_calls_for_is_device_registered(device_config, registered_device);
  
      STRICT_EXPECTED_CALL(amqp_device_unsubscribe_message(TEST_DEVICE_HANDLE));
  }
  
  static void set_expected_calls_for_prepare_device_for_connection_retry(DEVICE_STATE current_device_state)
  {
      set_expected_calls_for_on_methods_unsubscribed();
  
      if (current_device_state != DEVICE_STATE_STOPPED)
      {
          STRICT_EXPECTED_CALL(amqp_device_stop(TEST_DEVICE_HANDLE));
      }
  }
  
  static void set_expected_calls_for_prepare_for_connection_retry(int number_of_registered_devices, DEVICE_STATE current_device_state)
  {
      RETRY_ACTION retry_action = RETRY_ACTION_RETRY_NOW;
      STRICT_EXPECTED_CALL(retry_control_should_retry(TEST_RETRY_CONTROL_HANDLE, IGNORED_PTR_ARG))
          .CopyOutArgumentBuffer_retry_action(&retry_action, sizeof(RETRY_ACTION));
  
      STRICT_EXPECTED_CALL(xio_retrieveoptions(TEST_UNDERLYING_IO_TRANSPORT))
          .SetReturn(TEST_OPTIONHANDLER_HANDLE);
  
      EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_PTR_ARG));
  
      int i;
      for (i = 0; i < number_of_registered_devices; i++)
      {
          EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG));
          set_expected_calls_for_prepare_device_for_connection_retry(current_device_state);
          EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG));
      }
  
      STRICT_EXPECTED_CALL(amqp_connection_destroy(TEST_AMQP_CONNECTION_HANDLE));
      STRICT_EXPECTED_CALL(xio_destroy(TEST_UNDERLYING_IO_TRANSPORT));
  }
  
  // ---------- Test Hooks ---------- //
  static STRING_HANDLE TEST_STRING_construct_sprintf(const char* format, ...)
  {
      (void)format;
      return NULL;
  }
  
  static ON_METHODS_ERROR g_on_methods_error;
  static void* g_on_methods_error_context;
  static ON_METHOD_REQUEST_RECEIVED g_on_method_request_received;
  static void* g_on_method_request_received_context;
  static ON_METHODS_UNSUBSCRIBED g_on_methods_unsubscribed;
  static void* g_on_methods_unsubscribed_context;
  
  static int my_iothubtransportamqp_methods_subscribe(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle,
      SESSION_HANDLE session_handle, ON_METHODS_ERROR on_methods_error, void* on_methods_error_context,
      ON_METHOD_REQUEST_RECEIVED on_method_request_received, void* on_method_request_received_context,
      ON_METHODS_UNSUBSCRIBED on_methods_unsubscribed, void* on_methods_unsubscribed_context)
  {
      (void)iothubtransport_amqp_methods_handle, (void)session_handle;
      g_on_methods_error = on_methods_error;
      g_on_methods_error_context = on_methods_error_context;
      g_on_method_request_received = on_method_request_received;
      g_on_method_request_received_context = on_method_request_received_context;
      g_on_methods_unsubscribed = on_methods_unsubscribed;
      g_on_methods_unsubscribed_context = on_methods_unsubscribed_context;
      return 0;
  }
  
  static bool TEST_amqp_connection_create_saved_create_sasl_io;
  static bool TEST_amqp_connection_create_saved_create_cbs_connection;
  static ON_AMQP_CONNECTION_STATE_CHANGED TEST_amqp_connection_create_saved_on_state_changed_callback;
  static const void* TEST_amqp_connection_create_saved_on_state_changed_context;
  static size_t TEST_amqp_connection_create_saved_c2d_keep_alive_freq_secs;
  static double TEST_amqp_connection_create_saved_cl2svc_keep_alive_send_ratio;
  static AMQP_CONNECTION_HANDLE TEST_amqp_connection_create_return;
  static AMQP_CONNECTION_HANDLE TEST_amqp_connection_create(AMQP_CONNECTION_CONFIG* config)
  {
      TEST_amqp_connection_create_saved_create_sasl_io = config->create_sasl_io;
      TEST_amqp_connection_create_saved_create_cbs_connection = config->create_cbs_connection;
      TEST_amqp_connection_create_saved_on_state_changed_callback = config->on_state_changed_callback;
      TEST_amqp_connection_create_saved_on_state_changed_context = config->on_state_changed_context;
      TEST_amqp_connection_create_saved_c2d_keep_alive_freq_secs = config->svc2cl_keep_alive_timeout_secs;
      TEST_amqp_connection_create_saved_cl2svc_keep_alive_send_ratio = config->cl2svc_keep_alive_send_ratio;
  
      return TEST_amqp_connection_create_return;
  }
  
  static SESSION_HANDLE TEST_amqp_connection_get_session_handle_session_handle;
  static int TEST_amqp_connection_get_session_handle_return;
  static int TEST_amqp_connection_get_session_handle(AMQP_CONNECTION_HANDLE conn_handle, SESSION_HANDLE* session_handle)
  {
      (void)conn_handle;
      *session_handle = TEST_amqp_connection_get_session_handle_session_handle;
  
      return TEST_amqp_connection_get_session_handle_return;
  }
  
  static CBS_HANDLE TEST_amqp_connection_get_cbs_handle_cbs_handle;
  static int TEST_amqp_connection_get_cbs_handle_return;
  static int TEST_amqp_connection_get_cbs_handle(AMQP_CONNECTION_HANDLE conn_handle, CBS_HANDLE* cbs_handle)
  {
      (void)conn_handle;
      *cbs_handle = TEST_amqp_connection_get_cbs_handle_cbs_handle;
  
      return TEST_amqp_connection_get_cbs_handle_return;
  }
  
  static double TEST_get_difftime(time_t t1, time_t t0)
  {
      return difftime(t1, t0);
  }
  
  static ON_DEVICE_STATE_CHANGED TEST_device_create_saved_on_state_changed_callback;
  static void* TEST_device_create_saved_on_state_changed_context;
  static AMQP_DEVICE_HANDLE TEST_device_create_return;
  static AMQP_DEVICE_HANDLE TEST_device_create(AMQP_DEVICE_CONFIG* config)
  {
      TEST_device_create_saved_on_state_changed_callback = config->on_state_changed_callback;
      TEST_device_create_saved_on_state_changed_context = config->on_state_changed_context;
      return TEST_device_create_return;
  }
  
  static bool g_MessageCallback_return;
  static bool TEST_Transport_MessageCallback(MESSAGE_CALLBACK_INFO* messageData, void* ctx)
  {
      (void)ctx;
      if (g_MessageCallback_return)
      {
          if (messageData->transportContext != NULL)
          {
              free(messageData->transportContext->link_name);
              free(messageData->transportContext);
          }
          free(messageData);
      }
      return g_MessageCallback_return;
  }
  
  // ---------- Test Helpers ---------- //
  static const TRANSPORT_PROVIDER* TEST_get_iothub_client_transport_provider(void)
  {
      return TEST_TRANSPORT_PROVIDER;
  }
  
  static XIO_HANDLE TEST_amqp_get_io_transport_result;
  static AMQP_TRANSPORT_PROXY_OPTIONS* expected_AMQP_TRANSPORT_PROXY_OPTIONS;
  static int error_proxy_options;
  static XIO_HANDLE TEST_amqp_get_io_transport(const char* target_fqdn, const AMQP_TRANSPORT_PROXY_OPTIONS* amqp_transport_proxy_options)
  {
      (void)target_fqdn;
      (void)amqp_transport_proxy_options;
      error_proxy_options = 0;
      if (((expected_AMQP_TRANSPORT_PROXY_OPTIONS == NULL) && (amqp_transport_proxy_options != NULL)) ||
          ((expected_AMQP_TRANSPORT_PROXY_OPTIONS != NULL) && (amqp_transport_proxy_options == NULL)))
      {
          error_proxy_options = 1;
      }
      else
      {
          if (expected_AMQP_TRANSPORT_PROXY_OPTIONS != NULL)
          {
              if ((strcmp(expected_AMQP_TRANSPORT_PROXY_OPTIONS->host_address, amqp_transport_proxy_options->host_address) != 0) ||
                  ((expected_AMQP_TRANSPORT_PROXY_OPTIONS->username != NULL) && (amqp_transport_proxy_options->username != NULL) && (strcmp(expected_AMQP_TRANSPORT_PROXY_OPTIONS->username, amqp_transport_proxy_options->username) != 0)) ||
                  ((expected_AMQP_TRANSPORT_PROXY_OPTIONS->password != NULL) && (amqp_transport_proxy_options->password != NULL) && (strcmp(expected_AMQP_TRANSPORT_PROXY_OPTIONS->password, amqp_transport_proxy_options->password) != 0)))
              {
                  error_proxy_options = 1;
              }
          }
      }
      return TEST_amqp_get_io_transport_result;
  }
  
  static IOTHUB_CLIENT_CONFIG* create_client_config()
  {
      static IOTHUB_CLIENT_CONFIG client_config;
      client_config.protocol = TEST_PROTOCOL_PROVIDER;
      client_config.deviceId = TEST_DEVICE_ID_CHAR_PTR;
      client_config.deviceKey = TEST_DEVICE_KEY;
      client_config.deviceSasToken = TEST_DEVICE_SAS_TOKEN;
      client_config.iotHubName = TEST_IOT_HUB_NAME;
      client_config.iotHubSuffix = TEST_IOT_HUB_SUFFIX;
      client_config.protocolGatewayHostName = TEST_PROT_GW_HOSTNAME;
      return &client_config;
  }
  
  static IOTHUBTRANSPORT_CONFIG* create_transport_config()
  {
      static IOTHUBTRANSPORT_CONFIG config;
      config.upperConfig = create_client_config();
      config.waitingToSend = NULL;
      return &config;
  }
  
  static IOTHUB_DEVICE_CONFIG* create_device_config(const char* device_id, bool use_device_key)
  {
      static IOTHUB_DEVICE_CONFIG device_config;
      device_config.deviceId = device_id;
  
      if (use_device_key)
      {
          device_config.deviceKey = TEST_DEVICE_KEY;
          device_config.deviceSasToken = NULL;
      }
      else
      {
          device_config.deviceKey = NULL;
          device_config.deviceSasToken = TEST_DEVICE_SAS_TOKEN;
      }
  
      device_config.moduleId = NULL;
  
      return &device_config;
  }
  
  static IOTHUB_DEVICE_CONFIG* create_device_config_for_x509(const char* device_id)
  {
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(device_id, false);
      device_config->deviceSasToken = NULL;
      return device_config;
  }
  
  static TRANSPORT_LL_HANDLE create_transport()
  {
      IOTHUBTRANSPORT_CONFIG* config = create_transport_config();
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Create(config);
      TRANSPORT_LL_HANDLE handle = IoTHubTransport_AMQP_Common_Create(config, TEST_amqp_get_io_transport, &transport_cb_info, transport_cb_ctx);
  
      return handle;
  }
  
  static void crank_transport(void* handle, PDLIST_ENTRY wts, int wts_length, DEVICE_STATE current_device_state, bool is_tls_io_acquired, bool is_using_cbs, bool is_connection_created, bool is_connection_open, int number_of_registered_devices, time_t current_time, bool subscribe_for_methods)
  {
      umock_c_reset_all_calls();
      set_expected_calls_for_DoWork(wts, wts_length, current_device_state, is_tls_io_acquired, is_using_cbs, is_connection_created, is_connection_open, number_of_registered_devices, current_time, subscribe_for_methods);
      (void)IoTHubTransport_AMQP_Common_DoWork(handle);
  }
  
  static void crank_transport_ready_after_create(void* handle, PDLIST_ENTRY wts, int wts_length, bool is_tls_io_acquired, bool is_using_cbs, int number_of_registered_devices, time_t current_time, bool subscribe_for_methods)
  {
      crank_transport(handle, wts, wts_length, DEVICE_STATE_STOPPED, is_tls_io_acquired, is_using_cbs, false, false, number_of_registered_devices, current_time, false);
  
      TEST_amqp_connection_create_saved_on_state_changed_callback(
          TEST_amqp_connection_create_saved_on_state_changed_context,
          AMQP_CONNECTION_STATE_CLOSED, AMQP_CONNECTION_STATE_OPENED);
  
      crank_transport(handle, wts, wts_length, DEVICE_STATE_STOPPED, true, is_using_cbs, true, true, number_of_registered_devices, current_time, false);
  
      STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(TEST_current_time);
      STRICT_EXPECTED_CALL(retry_control_reset(TEST_RETRY_CONTROL_HANDLE));
      STRICT_EXPECTED_CALL(Transport_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_AUTHENTICATED, IOTHUB_CLIENT_CONNECTION_OK, IGNORED_PTR_ARG));
  
      TEST_device_create_saved_on_state_changed_callback(TEST_device_create_saved_on_state_changed_context,
          DEVICE_STATE_STOPPED, DEVICE_STATE_STARTED);
  
      crank_transport(handle, wts, wts_length, DEVICE_STATE_STARTED, true, is_using_cbs, true, true, number_of_registered_devices, current_time, subscribe_for_methods);
  }
  
  static IOTHUB_DEVICE_HANDLE register_device(TRANSPORT_LL_HANDLE handle, IOTHUB_DEVICE_CONFIG* device_config, PDLIST_ENTRY wts, bool is_using_cbs)
  {
      umock_c_reset_all_calls();
      set_expected_calls_for_Register(device_config, is_using_cbs);
      return IoTHubTransport_AMQP_Common_Register(handle, device_config, wts);
  }
  
  static void destroy_transport(TRANSPORT_LL_HANDLE handle, IOTHUB_DEVICE_HANDLE registered_device0, IOTHUB_DEVICE_HANDLE registered_device1)
  {
      int number_of_registered_devices = (registered_device1 != NULL ? 2 : (registered_device0 != NULL ? 1 : 0));
  
      IOTHUB_DEVICE_HANDLE registered_devices[2];
      registered_devices[0] = registered_device0;
      registered_devices[1] = registered_device1;
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Destroy(number_of_registered_devices, registered_devices);
      IoTHubTransport_AMQP_Common_Destroy(handle);
  }
  
  static DEVICE_TWIN_UPDATE_STATE get_twin_update_type;
  static const unsigned char* get_twin_message;
  static size_t get_twin_length;
  static void* get_twin_context;
  static void on_device_get_twin_completed_callback(DEVICE_TWIN_UPDATE_STATE update_type, const unsigned char* message, size_t length, void* context)
  {
      get_twin_update_type = update_type;
      get_twin_message = message;
      get_twin_length = length;
      get_twin_context = context;
  }
  
  // ---------- Test Initialization Helpers ---------- //
  static void register_umock_alias_types()
  {
      REGISTER_UMOCK_ALIAS_TYPE(AMQP_CONNECTION_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(AMQP_TYPE, int);
      REGISTER_UMOCK_ALIAS_TYPE(AMQP_VALUE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(AUTHENTICATION_STATE_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(BINARY_DATA, void*);
      REGISTER_UMOCK_ALIAS_TYPE(BUFFER_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(CBS_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(CONNECTION_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(AMQP_DEVICE_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(AMQP_DEVICE_CONFIG, void*);
      REGISTER_UMOCK_ALIAS_TYPE(DEVICE_MESSAGE_DISPOSITION_RESULT, int);
      REGISTER_UMOCK_ALIAS_TYPE(DEVICE_SEND_STATUS, int);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_RESULT, int);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_CONNECTION_STATUS, int);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_CONNECTION_STATUS_REASON, int);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_STATUS, int);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_CORE_LL_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_RETRY_POLICY, int);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_MESSAGE_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_MESSAGE_RESULT, void*);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUBMESSAGE_CONTENT_TYPE, int);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUBMESSAGE_DISPOSITION_RESULT, int);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUBTRANSPORT_AMQP_METHOD_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(LIST_ACTION_FUNCTION, void*);
      REGISTER_UMOCK_ALIAS_TYPE(LIST_MATCH_FUNCTION, void*);
      REGISTER_UMOCK_ALIAS_TYPE(MAP_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(MAP_RESULT, int);
      REGISTER_UMOCK_ALIAS_TYPE(METHOD_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_AMQP_CONNECTION_STATE_CHANGED, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_AMQP_MANAGEMENT_STATE_CHANGED, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_CONNECTION_STATE_CHANGED, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_DEVICE_C2D_MESSAGE_RECEIVED, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_DEVICE_D2C_EVENT_SEND_COMPLETE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_DEVICE_STATE_CHANGED, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_IO_ERROR, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_LINK_ATTACHED, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_MESSAGE_SENDER_STATE_CHANGED, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_METHODS_UNSUBSCRIBED, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_NEW_ENDPOINT, void*);
      REGISTER_UMOCK_ALIAS_TYPE(OPTIONHANDLER_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(OPTIONHANDLER_RESULT, int);
      REGISTER_UMOCK_ALIAS_TYPE(DLIST_ENTRY, void*);
      REGISTER_UMOCK_ALIAS_TYPE(PDLIST_ENTRY, void*);
      REGISTER_UMOCK_ALIAS_TYPE(const PDLIST_ENTRY, void*);
      REGISTER_UMOCK_ALIAS_TYPE(PREDICATE_FUNCTION, void*);
      REGISTER_UMOCK_ALIAS_TYPE(PROPERTIES_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(RETRY_CONTROL_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(SESSION_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(SINGLYLINKEDLIST_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(LIST_ITEM_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(STRING_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(time_t, int);
      REGISTER_UMOCK_ALIAS_TYPE(XIO_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(fields, void*);
      REGISTER_UMOCK_ALIAS_TYPE(role, bool);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_METHOD_REQUEST_RECEIVED, void*);
      REGISTER_UMOCK_ALIAS_TYPE(ON_METHODS_ERROR, void*);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_AUTHORIZATION_HANDLE, void*);
      REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, void*);
      REGISTER_UMOCK_ALIAS_TYPE(DEVICE_TWIN_UPDATE_RECEIVED_CALLBACK, void*);
  }
  
  static void register_global_mock_hooks()
  {
      REGISTER_GLOBAL_MOCK_HOOK(gballoc_malloc, TEST_malloc);
      REGISTER_GLOBAL_MOCK_HOOK(gballoc_free, TEST_free);
      REGISTER_GLOBAL_MOCK_HOOK(gballoc_realloc, my_gballoc_realloc);
      REGISTER_GLOBAL_MOCK_HOOK(iothubtransportamqp_methods_subscribe, my_iothubtransportamqp_methods_subscribe);
  
      REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_add, TEST_singlylinkedlist_add);
      REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_remove, TEST_singlylinkedlist_remove);
      REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_get_head_item, TEST_singlylinkedlist_get_head_item);
      REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_get_next_item, TEST_singlylinkedlist_get_next_item);
      REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_find, TEST_singlylinkedlist_find);
      REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_foreach, TEST_singlylinkedlist_foreach);
      REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_item_get_value, TEST_singlylinkedlist_item_get_value);
  
      REGISTER_GLOBAL_MOCK_HOOK(DList_RemoveEntryList, my_DList_RemoveEntryList);
      REGISTER_GLOBAL_MOCK_HOOK(DList_InsertTailList, my_DList_InsertTailList);
      REGISTER_GLOBAL_MOCK_HOOK(DList_IsListEmpty, my_DList_IsListEmpty);
      REGISTER_GLOBAL_MOCK_HOOK(DList_InitializeListHead, my_DList_InitializeListHead);
  
      REGISTER_GLOBAL_MOCK_HOOK(amqp_connection_create, TEST_amqp_connection_create);
      REGISTER_GLOBAL_MOCK_HOOK(amqp_connection_get_session_handle, TEST_amqp_connection_get_session_handle);
      REGISTER_GLOBAL_MOCK_HOOK(amqp_connection_get_cbs_handle, TEST_amqp_connection_get_cbs_handle);
  
      REGISTER_GLOBAL_MOCK_HOOK(get_difftime, TEST_get_difftime);
  
      REGISTER_GLOBAL_MOCK_HOOK(amqp_device_create, TEST_device_create);
      REGISTER_GLOBAL_MOCK_HOOK(amqp_device_subscribe_message, TEST_device_subscribe_message);
  
      REGISTER_GLOBAL_MOCK_HOOK(Transport_MessageCallback, TEST_Transport_MessageCallback);
      REGISTER_GLOBAL_MOCK_RETURN(Transport_GetOption_Product_Info_Callback, TEST_PRODUCT_INFO_CHAR_PTR);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(Transport_GetOption_Product_Info_Callback, NULL);
  
      REGISTER_GLOBAL_MOCK_HOOK(mallocAndStrcpy_s, TEST_mallocAndStrcpy_s);
  }
  
  static void register_global_mock_returns()
  {
      REGISTER_GLOBAL_MOCK_RETURN(iothubtransportamqp_methods_create, TEST_IOTHUBTRANSPORTAMQP_METHODS);
      REGISTER_GLOBAL_MOCK_RETURN(session_create, TEST_SESSION_HANDLE);
      REGISTER_GLOBAL_MOCK_RETURN(platform_get_default_tlsio, TEST_XIO_INTERFACE);
      REGISTER_GLOBAL_MOCK_RETURN(xio_create, TEST_XIO_HANDLE);
      REGISTER_GLOBAL_MOCK_RETURN(connection_create2, TEST_CONNECTION_HANDLE);
      REGISTER_GLOBAL_MOCK_RETURN(cbs_create, TEST_CBS_HANDLE);
      REGISTER_GLOBAL_MOCK_RETURN(BUFFER_new, TEST_BUFFER_HANDLE);
      REGISTER_GLOBAL_MOCK_RETURN(amqpvalue_create_map, TEST_AMQP_MAP);
      REGISTER_GLOBAL_MOCK_RETURN(amqpvalue_create_symbol, TEST_AMQP_VALUE);
      REGISTER_GLOBAL_MOCK_RETURN(amqpvalue_create_string, TEST_AMQP_VALUE);
  
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(singlylinkedlist_create, NULL);
  
      REGISTER_GLOBAL_MOCK_RETURN(amqp_device_start_async, 0);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(amqp_device_start_async, 1);
  
      REGISTER_GLOBAL_MOCK_RETURN(amqp_device_stop, 0);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(amqp_device_stop, 1);
  
      REGISTER_GLOBAL_MOCK_RETURN(IoTHub_Transport_ValidateCallbacks, 0);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(IoTHub_Transport_ValidateCallbacks, __LINE__);
  
      REGISTER_GLOBAL_MOCK_RETURN(amqp_device_set_option, 0);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(amqp_device_set_option, 1);
  
      REGISTER_GLOBAL_MOCK_RETURN(amqp_device_subscribe_message, 0);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(amqp_device_subscribe_message, 1);
  
      REGISTER_GLOBAL_MOCK_RETURN(amqp_device_unsubscribe_message, 0);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(amqp_device_unsubscribe_message, 1);
  
      REGISTER_GLOBAL_MOCK_RETURN(amqp_device_get_send_status, 0);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(amqp_device_get_send_status, 1);
  
      REGISTER_GLOBAL_MOCK_RETURN(amqp_device_send_message_disposition, 0);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(amqp_device_send_message_disposition, 1);
  
      REGISTER_GLOBAL_MOCK_RETURN(amqp_device_get_twin_async, 0);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(amqp_device_get_twin_async, 1);
  
      REGISTER_GLOBAL_MOCK_RETURN(OptionHandler_FeedOptions, OPTIONHANDLER_OK);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(OptionHandler_FeedOptions, OPTIONHANDLER_ERROR);
  
      REGISTER_GLOBAL_MOCK_RETURN(retry_control_create, TEST_RETRY_CONTROL_HANDLE);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(retry_control_create, NULL);
  
      REGISTER_GLOBAL_MOCK_RETURN(retry_control_set_option, 0);
      REGISTER_GLOBAL_MOCK_FAIL_RETURN(retry_control_set_option, 1);
  }
  
  static void reset_test_data()
  {
      g_STRING_sprintf_call_count = 0;
      g_STRING_sprintf_fail_on_count = 0;
  
      STRING_construct_sprintf_result = NULL;
      saved_STRING_sprintf_handle = NULL;
  
      TEST_amqp_get_io_transport_result = TEST_UNDERLYING_IO_TRANSPORT;
  
      TEST_amqp_connection_create_saved_on_state_changed_callback = NULL;
      TEST_amqp_connection_create_saved_on_state_changed_context = NULL;
      TEST_amqp_connection_create_return = TEST_AMQP_CONNECTION_HANDLE;
  
      TEST_amqp_connection_get_session_handle_session_handle = TEST_SESSION_HANDLE;
      TEST_amqp_connection_get_session_handle_return = 0;
  
      TEST_amqp_connection_get_cbs_handle_cbs_handle = TEST_CBS_HANDLE;
      TEST_amqp_connection_get_cbs_handle_return = 0;
  
      TEST_device_create_saved_on_state_changed_callback = NULL;
      TEST_device_create_saved_on_state_changed_context = NULL;
      TEST_device_create_return = TEST_DEVICE_HANDLE;
  
      saved_registered_devices_list_count = 0;
  
      TEST_device_subscribe_message_saved_callback = NULL;
      TEST_device_subscribe_message_saved_context = NULL;
      TEST_device_subscribe_message_return = 0;
  
      TEST_MESSAGE_ID = 1234;
      TEST_mallocAndStrcpy_s_return = 0;
  
      TEST_singlylinkedlist_foreach_list = NULL;
      TEST_singlylinkedlist_foreach_action_function = NULL;
      TEST_singlylinkedlist_foreach_context = NULL;
  
      memset(&TEST_waitingToSend, 0, sizeof(TEST_waitingToSend));
  
      g_on_methods_error_context = NULL;
      g_on_method_request_received_context = NULL;
      g_on_methods_unsubscribed_context = NULL;
      expected_AMQP_TRANSPORT_PROXY_OPTIONS = NULL;
  }
  
  static void initialize_test_variables()
  {
      TEST_current_time = time(NULL);
      ASSERT_IS_TRUE(INDEFINITE_TIME != TEST_current_time, "Failed setting TEST_current_time");
  
      real_DList_InitializeListHead(&TEST_waitingToSend);
  }
  
  
  BEGIN_TEST_SUITE(iothubtransport_amqp_common_ut)
  
  TEST_SUITE_INITIALIZE(TestClassInitialize)
  {
      g_testByTest = TEST_MUTEX_CREATE();
      ASSERT_IS_NOT_NULL(g_testByTest);
  
      umock_c_init(on_umock_c_error);
  
      int result = umocktypes_charptr_register_types();
      ASSERT_ARE_EQUAL(int, 0, result);
      result = umocktypes_stdint_register_types();
      ASSERT_ARE_EQUAL(int, 0, result);
      result = umocktypes_bool_register_types();
      ASSERT_ARE_EQUAL(int, 0, result);
  
      register_umock_alias_types();
      register_global_mock_hooks();
      register_global_mock_returns();
  
      transport_cb_info.send_complete_cb = Transport_SendComplete_Callback;
      transport_cb_info.twin_retrieve_prop_complete_cb = Transport_Twin_RetrievePropertyComplete_Callback;
      transport_cb_info.twin_rpt_state_complete_cb = Transport_Twin_ReportedStateComplete_Callback;
      transport_cb_info.send_complete_cb = Transport_SendComplete_Callback;
      transport_cb_info.connection_status_cb = Transport_ConnectionStatusCallBack;
      transport_cb_info.prod_info_cb = Transport_GetOption_Product_Info_Callback;
      transport_cb_info.msg_input_cb = Transport_MessageCallbackFromInput;
      transport_cb_info.msg_cb = Transport_MessageCallback;
      transport_cb_info.method_complete_cb = Transport_DeviceMethod_Complete_Callback;
  }
  
  TEST_SUITE_CLEANUP(TestClassCleanup)
  {
      umock_c_deinit();
  
      TEST_MUTEX_DESTROY(g_testByTest);
  }
  
  TEST_FUNCTION_INITIALIZE(TestMethodInitialize)
  {
      if (TEST_MUTEX_ACQUIRE(g_testByTest))
      {
          ASSERT_FAIL("our mutex is ABANDONED. Failure in test framework");
      }
  
      umock_c_reset_all_calls();
  
      reset_test_data();
  }
  
  TEST_FUNCTION_CLEANUP(TestMethodCleanup)
  {
      reset_test_data();
      TEST_MUTEX_RELEASE(g_testByTest);
  }
  
  /* IoTHubTransport_AMQP_Common_Register */
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_010: [ `IoTHubTransport_AMQP_Common_Register` shall create a new iothubtransportamqp_methods instance by calling `iothubtransportamqp_methods_create` while passing to it the the fully qualified domain name, the device Id, and optional module Id. ]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_Register_creates_a_new_methods_handler)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      initialize_test_variables();
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.moduleId = NULL;
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Register(&device_config, true);
  
      // act
      device_handle = IoTHubTransport_AMQP_Common_Register(handle, &device_config, &TEST_waitingToSend);
  
      // assert
      ASSERT_IS_NOT_NULL(device_handle);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_011: [ If `iothubtransportamqp_methods_create` fails, `IoTHubTransport_AMQP_Common_Register` shall fail and return NULL. ]*/
  TEST_FUNCTION(when_creating_the_methods_handler_fails_then_IoTHubTransport_AMQP_Common_Register_fails)
  {
      // arrange
      ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init());
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle = NULL;
  
      initialize_test_variables();
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.moduleId = NULL;
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Register(&device_config, true);
      umock_c_negative_tests_snapshot();
  
      // act
      size_t i;
      size_t n = umock_c_negative_tests_call_count();
      for (i = 0; i < n; i++)
      {
          if (umock_c_negative_tests_can_call_fail(i))
          {
              // arrange
              umock_c_negative_tests_reset();
              umock_c_negative_tests_fail_call(i);
  
              // act
              device_handle = IoTHubTransport_AMQP_Common_Register(handle, &device_config, &TEST_waitingToSend);
  
              // assert
              ASSERT_IS_NULL(device_handle, "On failed call %lu", (unsigned long)i);
          }
      }
  
      // cleanup
      umock_c_negative_tests_deinit();
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_012: [IoTHubTransport_AMQP_Common_Unregister shall destroy the C2D methods handler by calling iothubtransportamqp_methods_destroy.]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_Unregister_destroys_the_methods_handler)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      initialize_test_variables();
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      device_handle = register_device(handle, &device_config, &TEST_waitingToSend, true);
  
      (void)IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Unregister(device_handle);
  
      // act
      IoTHubTransport_AMQP_Common_Unregister(device_handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod */
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_004: [ If `handle` is NULL, `IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod` shall fail and return a non-zero value. ]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod_with_NULL_handle_fails)
  {
      // arrange
      int result;
  
      // act
      result = IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(NULL);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_026: [ `IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod` shall remember that a subscribe is to be performed in the next call to DoWork and on success it shall return 0. ]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod_with_valid_handle_succeeds)
  {
      // arrange
      int result;
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      initialize_test_variables();
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      device_handle = register_device(handle, &device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, true);
  
      umock_c_reset_all_calls();
  
      // act
      result = IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(int, 0, result);
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_026: [ `IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod` shall remember that a subscribe is to be performed in the next call to DoWork and on success it shall return 0. ]*/
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_027: [ The current session handle shall be passed to `iothubtransportamqp_methods_subscribe`. ]*/
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_031: [ Once the device is authenticated, `iothubtransportamqp_methods_subscribe` shall be invoked (subsequent DoWork calls shall not call it if already subscribed). ]
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod_After_Subscribe_succeeds)
  {
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      device_handle = register_device(handle, &device_config, &TEST_waitingToSend, true);
  
      (void)IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, true);
  
      umock_c_reset_all_calls();
  
      // act
      int result = IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(int, 0, result);
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_METHODS_12_001: [ `on_methods_unsubscribed` calls iothubtransportamqp_methods_unsubscribe. ]*/
  TEST_FUNCTION(on_methods_unsubscribed_CALLS_iothubtransportamqp_methods_unsubscribe)
  {
      // arrange
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      device_handle = register_device(handle, &device_config, &TEST_waitingToSend, true);
  
      (void)IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, true);
  
      ASSERT_IS_NOT_NULL(g_on_methods_unsubscribed);
      ASSERT_IS_NOT_NULL(g_on_methods_unsubscribed_context);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_on_methods_unsubscribed();
  
      // act
      g_on_methods_unsubscribed(g_on_methods_unsubscribed_context);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_METHODS_12_001: [ `on_methods_unsubscribed` calls iothubtransportamqp_methods_unsubscribe. ]*/
  TEST_FUNCTION(on_methods_unsubscribed_re_subscribes)
  {
      // arrange
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      device_handle = register_device(handle, &device_config, &TEST_waitingToSend, true);
  
      (void)IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, true);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_on_methods_unsubscribed();
      g_on_methods_unsubscribed(g_on_methods_unsubscribed_context);
  
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STARTED, true, true, true, true, 1, TEST_current_time, true /* here lies the difference */);
  
      // act
      (void)IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* IoTHubTransport_AMQP_Common_Unsubscribe_DeviceMethod */
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_006: [ If `handle` is NULL, `IoTHubTransport_AMQP_Common_Unsubscribe_DeviceMethod` shall do nothing. ]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_Unsubscribe_With_NULL_handle_does_nothing)
  {
      // arrange
      // act
      IoTHubTransport_AMQP_Common_Unsubscribe_DeviceMethod(NULL);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_007: [ `IoTHubTransport_AMQP_Common_Unsubscribe_DeviceMethod` shall unsubscribe from receiving C2D method requests by calling `iothubtransportamqp_methods_unsubscribe`. ]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_Unsubscribe_unsubscribes_from_receiving_methods)
  {
      // arrange
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      device_handle = register_device(handle, &device_config, &TEST_waitingToSend, true);
  
      (void)IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, true);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(iothubtransportamqp_methods_unsubscribe(TEST_IOTHUBTRANSPORTAMQP_METHODS));
  
      // act
      IoTHubTransport_AMQP_Common_Unsubscribe_DeviceMethod(device_handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_008: [ If the transport is not subscribed to receive C2D method requests then `IoTHubTransport_AMQP_Common_Unsubscribe_DeviceMethod` shall do nothing. ]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_Unsubscribe_without_subscribe_does_nothing)
  {
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      device_handle = register_device(handle, &device_config, &TEST_waitingToSend, true);
  
      (void)IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, true);
  
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(iothubtransportamqp_methods_unsubscribe(TEST_IOTHUBTRANSPORTAMQP_METHODS));
  
      // act
      IoTHubTransport_AMQP_Common_Unsubscribe_DeviceMethod(device_handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* IoTHubTransport_AMQP_Common_DoWork */
  
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_DoWork_does_not_subscribe_if_SubScribe_for_methods_was_not_Called_by_the_user)
  {
      // arrange
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      device_handle = register_device(handle, &device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STARTED, true, true, true, true, 1, TEST_current_time, false);
  
      // act
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_031: [ `iothubtransportamqp_methods_subscribe` shall only be called once (subsequent DoWork calls shall not call it if already subscribed). ]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_DoWork_does_not_subscribe_if_already_subscribed)
  {
      // arrange
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      device_handle = register_device(handle, &device_config, &TEST_waitingToSend, true);
  
      (void)IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, true);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STARTED, true, true, true, true, 1, TEST_current_time, false);
  
      // act
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* on_methods_request_received */
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_028: [ On success, `on_methods_request_received` shall return 0. ]*/
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_016: [ `on_methods_request_received` shall create a BUFFER_HANDLE by calling `BUFFER_new`. ]*/
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_017: [ `on_methods_request_received` shall call the `IoTHubClientCore_LL_DeviceMethodComplete` passing the method name, request buffer and size and the newly created BUFFER handle. ]*/
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_020: [ The response bytes shall be obtained by calling `BUFFER_u_char`. ]*/
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_021: [ The response size shall be obtained by calling `BUFFER_length`. ]*/
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_022: [ The status code shall be the return value of the call to `IoTHubClientCore_LL_DeviceMethodComplete`. ]*/
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_023: [ After calling `iothubtransportamqp_methods_respond`, the allocated buffer shall be freed by using BUFFER_delete. ]*/
  TEST_FUNCTION(on_methods_request_received_responds_to_the_method_request)
  {
      // arrange
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      static unsigned char test_request_payload[] = { 0x42, 0x43 };
      static unsigned char test_method_response[] = { 0x44, 0x45 };
      int result;
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Register(&device_config, true);
      device_handle = IoTHubTransport_AMQP_Common_Register(handle, &device_config, &TEST_waitingToSend);
  
      (void)IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, true);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(Transport_DeviceMethod_Complete_Callback("test_method", IGNORED_PTR_ARG, sizeof(test_method_response), IGNORED_PTR_ARG, IGNORED_PTR_ARG));
  
      // act
      result = g_on_method_request_received(g_on_method_request_received_context, "test_method", test_request_payload, sizeof(test_request_payload), TEST_METHOD_HANDLE);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(int, 0, result);
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_029: [ If `iothubtransportamqp_methods_respond` fails, `iothubtransportamqp_methods_respond` shall return a non-zero value. ]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_DeviceMethod_Response_succeed)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
  
      initialize_test_variables();
  
      handle = create_transport();
  
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(iothubtransportamqp_methods_respond(TEST_METHOD_HANDLE, TEST_DEVICE_METHOD_RESPONSE, TEST_DEVICE_RESP_LENGTH, TEST_DEVICE_STATUS_CODE));
  
      // act
      int result = IoTHubTransport_AMQP_Common_DeviceMethod_Response(handle, (METHOD_HANDLE)TEST_METHOD_HANDLE, TEST_DEVICE_METHOD_RESPONSE, TEST_DEVICE_RESP_LENGTH, TEST_DEVICE_STATUS_CODE);
  
      // assert
      ASSERT_ARE_EQUAL(int, 0, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_029: [ If `iothubtransportamqp_methods_respond` fails, `iothubtransportamqp_methods_respond` shall return a non-zero value. ]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_DeviceMethod_Response_fail)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
  
      initialize_test_variables();
  
      handle = create_transport();
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(iothubtransportamqp_methods_respond(TEST_METHOD_HANDLE, TEST_DEVICE_METHOD_RESPONSE, TEST_DEVICE_RESP_LENGTH, TEST_DEVICE_STATUS_CODE))
          .SetReturn(1);
  
      // act
      int result = IoTHubTransport_AMQP_Common_DeviceMethod_Response(handle, TEST_METHOD_HANDLE, TEST_DEVICE_METHOD_RESPONSE, TEST_DEVICE_RESP_LENGTH, TEST_DEVICE_STATUS_CODE);
  
      // assert
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  /* on_methods_error */
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_030: [ `on_methods_error` shall do nothing. ]*/
  TEST_FUNCTION(on_methods_error_does_nothing)
  {
      // arrange
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUB_DEVICE_CONFIG device_config;
      IOTHUB_DEVICE_HANDLE device_handle;
  
      handle = create_transport();
  
      device_config.deviceId = "blah";
      device_config.deviceKey = "cucu";
      device_config.deviceSasToken = NULL;
      device_config.moduleId = NULL;
  
      device_handle = register_device(handle, &device_config, &TEST_waitingToSend, true);
  
      (void)IoTHubTransport_AMQP_Common_Subscribe_DeviceMethod(device_handle);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, true);
  
      umock_c_reset_all_calls();
  
      // act
      g_on_methods_error(g_on_methods_error_context);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_001: [If `config` or `config->upperConfig` or `get_io_transport` are NULL then IoTHubTransport_AMQP_Common_Create shall fail and return NULL.]
  TEST_FUNCTION(AMQP_Create_NULL_config)
  {
      // arrange
      umock_c_reset_all_calls();
  
      // act
      TRANSPORT_LL_HANDLE tr_hdl = IoTHubTransport_AMQP_Common_Create(NULL, NULL, &transport_cb_info, transport_cb_ctx);
  
      // assert
      ASSERT_IS_NULL(tr_hdl, "Expected NULL transport handle");
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_001: [If `config` or `config->upperConfig` or `get_io_transport` are NULL then IoTHubTransport_AMQP_Common_Create shall fail and return NULL.]
  TEST_FUNCTION(AMQP_Create_NULL_upperConfig)
  {
      // arrange
      IOTHUBTRANSPORT_CONFIG config;
      config.upperConfig = NULL;
  
      umock_c_reset_all_calls();
  
      // act
      TRANSPORT_LL_HANDLE tr_hdl = IoTHubTransport_AMQP_Common_Create(&config, TEST_amqp_get_io_transport, &transport_cb_info, transport_cb_ctx);
  
      // assert
      ASSERT_IS_NULL(tr_hdl);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_001: [If `config` or `config->upperConfig` or `get_io_transport` are NULL then IoTHubTransport_AMQP_Common_Create shall fail and return NULL.]
  TEST_FUNCTION(AMQP_Create_upperConfig_protocol_NULL)
  {
      // arrange
      IOTHUBTRANSPORT_CONFIG* config = create_transport_config();
  
      umock_c_reset_all_calls();
  
      // act
      TRANSPORT_LL_HANDLE handle = IoTHubTransport_AMQP_Common_Create(config, TEST_amqp_get_io_transport, &transport_cb_info, transport_cb_ctx);
  
      // assert
      ASSERT_IS_NULL(handle);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_001: [If `config` or `config->upperConfig` or `get_io_transport` are NULL then IoTHubTransport_AMQP_Common_Create shall fail and return NULL.]
  TEST_FUNCTION(AMQP_Create_upperConfig_iotHubName_NULL)
  {
      // arrange
      IOTHUB_CLIENT_CONFIG client_config;
      client_config.protocol = NULL;
      client_config.deviceId = TEST_DEVICE_ID_CHAR_PTR;
      client_config.deviceKey = TEST_DEVICE_KEY;
      client_config.deviceSasToken = TEST_DEVICE_SAS_TOKEN;
      client_config.iotHubName = NULL;
      client_config.iotHubSuffix = TEST_IOT_HUB_SUFFIX;
      client_config.protocolGatewayHostName = TEST_PROT_GW_HOSTNAME;
  
      IOTHUBTRANSPORT_CONFIG config;
      config.upperConfig = &client_config;
      config.waitingToSend = NULL;
  
      umock_c_reset_all_calls();
  
      // act
      TRANSPORT_LL_HANDLE handle = IoTHubTransport_AMQP_Common_Create(&config, TEST_amqp_get_io_transport, &transport_cb_info, transport_cb_ctx);
  
      // assert
      ASSERT_IS_NULL(handle);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_02_001: [**If `handle` is NULL, `IoTHubTransport_AMQP_Common_GetHostname` shall return NULL.**]**
  TEST_FUNCTION(GetHostName_NULL_handle)
  {
      // arrange
  
      // act
      STRING_HANDLE result = IoTHubTransport_AMQP_Common_GetHostname(NULL);
  
      // assert
      ASSERT_ARE_EQUAL(void_ptr, NULL, result);
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_02_002: [**IoTHubTransport_AMQP_Common_GetHostname shall return a copy of `instance->iothub_target_fqdn`.**]**
  TEST_FUNCTION(GetHostName_success)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      umock_c_reset_all_calls();
      set_expected_calls_for_GetHostname();
  
      // act
      STRING_HANDLE result = IoTHubTransport_AMQP_Common_GetHostname(handle);
  
      // assert
      ASSERT_ARE_EQUAL(void_ptr, TEST_IOTHUB_HOST_FQDN_CLONE_STRING_HANDLE, result);
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_003: [Memory shall be allocated for the transport's internal state structure (`instance`)]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_005: [If `config->upperConfig->protocolGatewayHostName` is NULL, `instance->iothub_target_fqdn` shall be set as `config->upperConfig->iotHubName` + "." + `config->upperConfig->iotHubSuffix`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_006: [If `config->upperConfig->protocolGatewayHostName` is not NULL, `instance->iothub_target_fqdn` shall be set with a copy of it]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_008: [`instance->registered_devices` shall be set using singlylinkedlist_create()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_010: [`get_io_transport` shall be saved on `instance->underlying_io_transport_provider`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_012: [If IoTHubTransport_AMQP_Common_Create succeeds it shall return a pointer to `instance`.]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_124: [`instance->connection_retry_control` shall be set using retry_control_create(), passing defaults EXPONENTIAL_BACKOFF_WITH_JITTER and 0]
  TEST_FUNCTION(Create_success)
  {
      // arrange
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUBTRANSPORT_CONFIG* config = create_transport_config();
  
      set_expected_calls_for_Create(config);
  
      // act
      handle = IoTHubTransport_AMQP_Common_Create(config, TEST_amqp_get_io_transport, &transport_cb_info, transport_cb_ctx);
  
      // assert
      ASSERT_IS_NOT_NULL(handle);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_Create_callbacks_NULL_fail)
  {
      // arrange
      initialize_test_variables();
  
      TRANSPORT_LL_HANDLE handle;
      IOTHUBTRANSPORT_CONFIG* config = create_transport_config();
  
      // act
      handle = IoTHubTransport_AMQP_Common_Create(config, TEST_amqp_get_io_transport, NULL, transport_cb_ctx);
  
      // assert
      ASSERT_IS_NULL(handle);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_002: [IoTHubTransport_AMQP_Common_Create shall fail and return NULL if `config->upperConfig->protocol` is NULL]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_004: [If malloc() fails, IoTHubTransport_AMQP_Common_Create shall fail and return NULL]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_007: [If `instance->iothub_target_fqdn` fails to be set, IoTHubTransport_AMQP_Common_Create shall fail and return NULL]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_009: [If singlylinkedlist_create() fails, IoTHubTransport_AMQP_Common_Create shall fail and return NULL]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_011: [If IoTHubTransport_AMQP_Common_Create fails it shall free any memory it allocated]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_125: [If retry_control_create() fails, IoTHubTransport_AMQP_Common_Create shall fail and return NULL]
  TEST_FUNCTION(Create_failure_checks)
  {
      // arrange
      initialize_test_variables();
  
      ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init());
      TRANSPORT_LL_HANDLE handle;
      IOTHUBTRANSPORT_CONFIG* config = create_transport_config();
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Create(config);
      umock_c_negative_tests_snapshot();
  
      // act
      size_t i;
      for (i = 0; i < umock_c_negative_tests_call_count(); i++)
      {
          // arrange
          char error_msg[64];
  
          umock_c_negative_tests_reset();
          umock_c_negative_tests_fail_call(i);
  
          // act
          handle = IoTHubTransport_AMQP_Common_Create(config, TEST_amqp_get_io_transport, &transport_cb_info, transport_cb_ctx);
  
          // assert
          sprintf(error_msg, "On failed call %lu", (unsigned long)i);
          ASSERT_IS_NULL(handle, error_msg);
      }
  
      // cleanup
      umock_c_negative_tests_deinit();
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_013: [If `handle` is NULL, IoTHubTransport_AMQP_Common_Destroy shall return immediatelly]
  TEST_FUNCTION(Destroy_NULL_handle)
  {
      // arrange
      initialize_test_variables();
      umock_c_reset_all_calls();
  
      // act
      IoTHubTransport_AMQP_Common_Destroy(NULL);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_014: [IoTHubTransport_AMQP_Common_Destroy shall invoke IoTHubTransport_AMQP_Common_Unregister on each of its registered devices.]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_015: [All members of `instance` (including tls_io) shall be destroyed and its memory released]
  TEST_FUNCTION(Destroy_success)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE registered_devices[1];
      registered_devices[0] = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      set_expected_calls_for_Destroy(1, registered_devices);
  
      // act
      IoTHubTransport_AMQP_Common_Destroy(handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_17_005: [If `handle`, `device`, `iotHubClientHandle` or `waitingToSend` is NULL, IoTHubTransport_AMQP_Common_Register shall return NULL]
  TEST_FUNCTION(Register_NULL_wts)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      // act
      IOTHUB_DEVICE_HANDLE device_handle = IoTHubTransport_AMQP_Common_Register(handle, device_config, NULL);
  
      // assert
      ASSERT_IS_NULL(device_handle);
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_17_005: [If `handle`, `device`, `iotHubClientHandle` or `waitingToSend` is NULL, IoTHubTransport_AMQP_Common_Register shall return NULL]
  TEST_FUNCTION(Register_NULL_device_config)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      // act
      IOTHUB_DEVICE_HANDLE device_handle = IoTHubTransport_AMQP_Common_Register(handle, NULL, &TEST_waitingToSend);
  
      // assert
      ASSERT_IS_NULL(device_handle);
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_17_005: [If `handle`, `device`, `iotHubClientHandle` or `waitingToSend` is NULL, IoTHubTransport_AMQP_Common_Register shall return NULL]
  TEST_FUNCTION(Register_NULL_transport_handle)
  {
      // arrange
      initialize_test_variables();
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      // act
      IOTHUB_DEVICE_HANDLE device_handle = IoTHubTransport_AMQP_Common_Register(NULL, device_config, &TEST_waitingToSend);
  
      // assert
      ASSERT_IS_NULL(device_handle);
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_03_002: [IoTHubTransport_AMQP_Common_Register shall return NULL if `device->deviceId` is NULL.]
  TEST_FUNCTION(Register_NULL_config_device_id)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      device_config->deviceId = NULL;
  
      // act
      IOTHUB_DEVICE_HANDLE device_handle = IoTHubTransport_AMQP_Common_Register(handle, device_config, &TEST_waitingToSend);
  
      // assert
      ASSERT_IS_NULL(device_handle);
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_064: [If the device is already registered, IoTHubTransport_AMQP_Common_Register shall fail and return NULL.]
  TEST_FUNCTION(Register_device_already_registered)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      STRICT_EXPECTED_CALL(singlylinkedlist_find(TEST_REGISTERED_DEVICES_LIST, IGNORED_PTR_ARG, device_config->deviceId))
          .IgnoreArgument(2)
          .SetReturn(TEST_LIST_ITEM_HANDLE);
  
      // act
      IOTHUB_DEVICE_HANDLE device_handle = IoTHubTransport_AMQP_Common_Register(handle, device_config, &TEST_waitingToSend);
  
      // assert
      ASSERT_IS_NULL(device_handle);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_065: [IoTHubTransport_AMQP_Common_Register shall fail and return NULL if the device is not using an authentication mode compatible with the currently used by the transport.]
  TEST_FUNCTION(Register_CBS_transport_X509_credentials)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config1 = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE device_handle1 = register_device(handle, device_config1, &TEST_waitingToSend, true);
  
      IOTHUB_DEVICE_CONFIG* device_config2 = create_device_config(TEST_DEVICE_ID_2_CHAR_PTR, true);
      device_config2->deviceKey = NULL;
  
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(singlylinkedlist_find(TEST_REGISTERED_DEVICES_LIST, IGNORED_PTR_ARG, device_config2->deviceId))
          .IgnoreArgument(2)
          .SetReturn(NULL);
  
      // act
      IOTHUB_DEVICE_HANDLE device_handle2 = IoTHubTransport_AMQP_Common_Register(handle, device_config2, &TEST_waitingToSend);
  
      // assert
      ASSERT_IS_NOT_NULL(device_handle1);
      ASSERT_IS_NULL(device_handle2);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle1, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_065: [IoTHubTransport_AMQP_Common_Register shall fail and return NULL if the device is not using an authentication mode compatible with the currently used by the transport.]
  TEST_FUNCTION(Register_X509_transport_CBS_credentials)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config1 = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      device_config1->deviceKey = NULL;
  
      IOTHUB_DEVICE_HANDLE device_handle1 = register_device(handle, device_config1, &TEST_waitingToSend, false);
  
      IOTHUB_DEVICE_CONFIG* device_config2 = create_device_config(TEST_DEVICE_ID_2_CHAR_PTR, true);
  
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(singlylinkedlist_find(TEST_REGISTERED_DEVICES_LIST, IGNORED_PTR_ARG, device_config2->deviceId))
          .IgnoreArgument(2)
          .SetReturn(NULL);
  
      // act
      IOTHUB_DEVICE_HANDLE device_handle2 = IoTHubTransport_AMQP_Common_Register(handle, device_config2, &TEST_waitingToSend);
  
      // assert
      ASSERT_IS_NOT_NULL(device_handle1);
      ASSERT_IS_NULL(device_handle2);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle1, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_067: [If malloc fails, IoTHubTransport_AMQP_Common_Register shall fail and return NULL.]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_070: [If STRING_construct() fails, IoTHubTransport_AMQP_Common_Register shall fail and return NULL]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_073: [If amqp_device_create() fails, IoTHubTransport_AMQP_Common_Register shall fail and return NULL]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_011: [ If `iothubtransportamqp_methods_create` fails, `IoTHubTransport_AMQP_Common_Register` shall fail and return NULL]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_075: [If it fails to add `amqp_device_instance`, IoTHubTransport_AMQP_Common_Register shall fail and return NULL]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_077: [If IoTHubTransport_AMQP_Common_Register fails, it shall free all memory it allocated]
  TEST_FUNCTION(Register_failure_checks)
  {
      // arrange
      initialize_test_variables();
      ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init());
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Register(device_config, true);
      umock_c_negative_tests_snapshot();
  
      // act
      size_t i, n = umock_c_negative_tests_call_count();
      for (i = 0; i < n; i++)
      {
          if (i == 0 || i == 2 || i == 3 || i == 4 || i >= 5)
          {
              // These expected calls do not cause the API to fail.
              continue;
          }
  
          // arrange
          char error_msg[64];
  
          umock_c_negative_tests_reset();
          umock_c_negative_tests_fail_call(i);
  
          // act
          IOTHUB_DEVICE_HANDLE device_handle = IoTHubTransport_AMQP_Common_Register(handle, device_config, &TEST_waitingToSend);
  
          // assert
          sprintf(error_msg, "On failed call %lu", (unsigned long)i);
          ASSERT_IS_NULL(device_handle, error_msg);
      }
  
      // cleanup
      umock_c_negative_tests_deinit();
      destroy_transport(handle, NULL, NULL);
  }
  
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_066: [IoTHubTransport_AMQP_Common_Register shall allocate an instance of AMQP_TRANSPORT_DEVICE_STATE to store the state of the new registered device.]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_068: [IoTHubTransport_AMQP_Common_Register shall save the handle references to the IoTHubClient, transport, waitingToSend list on `amqp_device_instance`.]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_069: [A copy of `config->deviceId` shall be saved into `device_state->device_id`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_071: [`amqp_device_instance->device_handle` shall be set using amqp_device_create()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_072: [The configuration for amqp_device_create shall be set according to the authentication preferred by IOTHUB_DEVICE_CONFIG]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_010: [ `IoTHubTransport_AMQP_Common_Register` shall create a new iothubtransportamqp_methods instance by calling `iothubtransportamqp_methods_create` while passing to it the the fully qualified domain name, the device Id, and optional module Id.]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_074: [IoTHubTransport_AMQP_Common_Register shall add the `amqp_device_instance` to `instance->registered_devices`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_076: [If the device is the first being registered on the transport, IoTHubTransport_AMQP_Common_Register shall save its authentication mode as the transport preferred authentication mode]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_078: [IoTHubTransport_AMQP_Common_Register shall return a handle to `amqp_device_instance` as a IOTHUB_DEVICE_HANDLE]
  TEST_FUNCTION(Register_succeeds)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Register(device_config, true);
  
      // act
      IOTHUB_DEVICE_HANDLE device_handle = IoTHubTransport_AMQP_Common_Register(handle, device_config, &TEST_waitingToSend);
  
      // assert
      ASSERT_IS_NOT_NULL(device_handle);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_084: [If `handle` is NULL, IoTHubTransport_AMQP_Common_Subscribe shall return a non-zero result]
  TEST_FUNCTION(Subscribe_NULL_handle)
  {
      // arrange
      initialize_test_variables();
      umock_c_reset_all_calls();
  
      // act
      int result = IoTHubTransport_AMQP_Common_Subscribe(NULL);
  
      // assert
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_085: [If `amqp_device_instance` is not registered, IoTHubTransport_AMQP_Common_Subscribe shall return a non-zero result]
  TEST_FUNCTION(Subscribe_device_not_registered)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_is_device_registered(device_config, NULL);
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_DEVICE_ID_STRING_HANDLE))
          .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
  
      // act
      int result = IoTHubTransport_AMQP_Common_Subscribe(device_handle);
  
      // assert
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_086: [amqp_device_subscribe_message() shall be invoked passing `on_message_received_callback`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_088: [If no failures occur, IoTHubTransport_AMQP_Common_Subscribe shall return 0]
  TEST_FUNCTION(Subscribe_messages_succeeds)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Subscribe(device_config, device_handle);
  
      // act
      int result = IoTHubTransport_AMQP_Common_Subscribe(device_handle);
  
      // assert
      ASSERT_ARE_EQUAL(int, 0, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_087: [If amqp_device_subscribe_message() fails, IoTHubTransport_AMQP_Common_Subscribe shall return a non-zero result]
  TEST_FUNCTION(Subscribe_messages_failure_checks)
  {
      // arrange
      initialize_test_variables();
      ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init());
  
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Subscribe(device_config, device_handle);
      umock_c_negative_tests_snapshot();
  
      // act
      size_t i;
      for (i = 0; i < umock_c_negative_tests_call_count(); i++)
      {
          if (i == 0 || i == 1)
          {
              continue;
          }
  
          // arrange
          char error_msg[64];
          umock_c_negative_tests_reset();
          umock_c_negative_tests_fail_call(i);
  
          // act
          int result = IoTHubTransport_AMQP_Common_Subscribe(device_handle);
  
          // assert
          sprintf(error_msg, "On failed call %lu", (unsigned long)i);
          ASSERT_ARE_NOT_EQUAL(int, 0, result, error_msg);
      }
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
      umock_c_negative_tests_deinit();
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_093: [If `handle` is NULL, IoTHubTransport_AMQP_Common_Subscribe shall return]
  TEST_FUNCTION(Unsubscribe_NULL_handle)
  {
      // arrange
      initialize_test_variables();
      umock_c_reset_all_calls();
  
      // act
      IoTHubTransport_AMQP_Common_Unsubscribe(NULL);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_094: [If `amqp_device_instance` is not registered, IoTHubTransport_AMQP_Common_Subscribe shall return]
  TEST_FUNCTION(Unsubscribe_messages_device_not_registered)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_is_device_registered(device_config, NULL);
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_DEVICE_ID_STRING_HANDLE))
          .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
  
      // act
      IoTHubTransport_AMQP_Common_Unsubscribe(device_handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_095: [amqp_device_unsubscribe_message() shall be invoked passing `amqp_device_instance->device_handle`]
  TEST_FUNCTION(Unsubscribe_messages_succeeds)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Subscribe(device_config, device_handle);
      (void)IoTHubTransport_AMQP_Common_Subscribe(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Unsubscribe(device_config, device_handle);
  
      // act
      IoTHubTransport_AMQP_Common_Unsubscribe(device_handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_096: [If `handle` or `iotHubClientStatus` are NULL, IoTHubTransport_AMQP_Common_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG]
  TEST_FUNCTION(GetSendStatus_NULL_handle)
  {
      // arrange
      initialize_test_variables();
      umock_c_reset_all_calls();
  
      IOTHUB_CLIENT_STATUS iotHubClientStatus;
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_GetSendStatus(NULL, &iotHubClientStatus);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_096: [If `handle` or `iotHubClientStatus` are NULL, IoTHubTransport_AMQP_Common_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG]
  TEST_FUNCTION(GetSendStatus_NULL_iotHubClientStatus)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_GetSendStatus(device_handle, NULL);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_098: [If amqp_device_get_send_status() fails, IoTHubTransport_AMQP_Common_GetSendStatus shall return IOTHUB_CLIENT_ERROR]
  TEST_FUNCTION(GetSendStatus_failure_checks)
  {
      // arrange
      initialize_test_variables();
      ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init());
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_GetSendStatus(true, DEVICE_SEND_STATUS_IDLE);
      umock_c_negative_tests_snapshot();
  
      // act
      size_t i;
      for (i = 0; i < umock_c_negative_tests_call_count(); i++)
      {
          if (!umock_c_negative_tests_can_call_fail(i))
          {
              continue;
          }
  
          // arrange
          char error_msg[64];
          IOTHUB_CLIENT_STATUS iotHubClientStatus;
  
          umock_c_negative_tests_reset();
          umock_c_negative_tests_fail_call(i);
  
          // act
          IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_GetSendStatus(device_handle, &iotHubClientStatus);
  
          // assert
          sprintf(error_msg, "On failed call %lu", (unsigned long)i);
          ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result, error_msg);
      }
  
      // cleanup
      umock_c_negative_tests_deinit();
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_097: [IoTHubTransport_AMQP_Common_GetSendStatus shall invoke amqp_device_get_send_status()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_100: [If amqp_device_get_send_status() returns DEVICE_SEND_STATUS_IDLE, IoTHubTransport_AMQP_Common_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_STATUS_IDLE]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_109: [If no failures occur, IoTHubTransport_AMQP_Common_GetSendStatus shall return IOTHUB_CLIENT_OK]
  TEST_FUNCTION(GetSendStatus_IDLE_succeeds)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_GetSendStatus(true, DEVICE_SEND_STATUS_IDLE);
  
      IOTHUB_CLIENT_STATUS iotHubClientStatus;
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_GetSendStatus(device_handle, &iotHubClientStatus);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result);
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_SEND_STATUS_IDLE, iotHubClientStatus);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_099: [If amqp_device_get_send_status() returns DEVICE_SEND_STATUS_BUSY, IoTHubTransport_AMQP_Common_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_STATUS_BUSY]
  TEST_FUNCTION(GetSendStatus_BUSY_succeeds)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_GetSendStatus(true, DEVICE_SEND_STATUS_BUSY);
  
      IOTHUB_CLIENT_STATUS iotHubClientStatus;
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_GetSendStatus(device_handle, &iotHubClientStatus);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result);
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_SEND_STATUS_BUSY, iotHubClientStatus);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  TEST_FUNCTION(GetSendStatus_waiting_to_send_not_empty_BUSY)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_GetSendStatus(false, DEVICE_SEND_STATUS_BUSY);
  
      IOTHUB_CLIENT_STATUS iotHubClientStatus;
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_GetSendStatus(device_handle, &iotHubClientStatus);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result);
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_SEND_STATUS_BUSY, iotHubClientStatus);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_101: [If `handle`, `option` or `value` are NULL then IoTHubTransport_AMQP_Common_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]
  TEST_FUNCTION(SetOption_NULL_handle)
  {
      // arrange
      initialize_test_variables();
      umock_c_reset_all_calls();
  
      // act
      size_t value = 10;
      int result = IoTHubTransport_AMQP_Common_SetOption(NULL, OPTION_EVENT_SEND_TIMEOUT_SECS, &value);
  
      // assert
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_101: [If `handle`, `option` or `value` are NULL then IoTHubTransport_AMQP_Common_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]
  TEST_FUNCTION(SetOption_NULL_name)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      // act
      size_t value = 10;
      int result = IoTHubTransport_AMQP_Common_SetOption(handle, NULL, &value);
  
      // assert
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_101: [If `handle`, `option` or `value` are NULL then IoTHubTransport_AMQP_Common_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]
  TEST_FUNCTION(SetOption_NULL_value)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      // act
      int result = IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_EVENT_SEND_TIMEOUT_SECS, NULL);
  
      // assert
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_102: [If `option` is a device-specific option, it shall be saved and applied to each registered device using amqp_device_set_option()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_103: [If amqp_device_set_option() fails, IoTHubTransport_AMQP_Common_SetOption shall return IOTHUB_CLIENT_ERROR]
  TEST_FUNCTION(SetOption_device_specific_failure_check)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      size_t value = 10;
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(TEST_REGISTERED_DEVICES_LIST));
      EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG)).SetReturn(device_handle);
      STRICT_EXPECTED_CALL(amqp_device_set_option(TEST_DEVICE_HANDLE, DEVICE_OPTION_EVENT_SEND_TIMEOUT_SECS, &value))
          .SetReturn(1);
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_DEVICE_ID_STRING_HANDLE))
          .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_EVENT_SEND_TIMEOUT_SECS, &value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_02_007: [ If `option` is `x509certificate` and the transport preferred authentication method is not x509 then IoTHubTransport_AMQP_Common_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]
  TEST_FUNCTION(SetOption_CBS_transport_option_x509certificate)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      const char* value = "cert info";
  
      umock_c_reset_all_calls();
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_X509_CERT, value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_02_008: [ If `option` is `x509privatekey` and the transport preferred authentication method is not x509 then IoTHubTransport_AMQP_Common_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]
  TEST_FUNCTION(SetOption_CBS_transport_option_x509privatekey)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      const char* value = "cert info";
  
      umock_c_reset_all_calls();
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_X509_PRIVATE_KEY, value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_104: [If `option` is `logtrace`, `value` shall be saved and applied to `instance->connection` using amqp_connection_set_logging()]
  TEST_FUNCTION(SetOption_log_trace)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      // This creates the amqp_connection_handle
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      bool value = true;
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(amqp_connection_set_logging(TEST_AMQP_CONNECTION_HANDLE, value))
          .IgnoreArgument(2)
          .SetReturn(0);
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_LOG_TRACE, &value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_105: [If `option` does not match one of the options handled by this module, it shall be passed to `instance->tls_io` using xio_setoption()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_106: [If `instance->tls_io` is NULL, it shall be set invoking instance->underlying_io_transport_provider()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_108: [When `instance->tls_io` is created, IoTHubTransport_AMQP_Common_SetOption shall apply `instance->saved_tls_options` with OptionHandler_FeedOptions()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_03_001: [If no failures occur, IoTHubTransport_AMQP_Common_SetOption shall return IOTHUB_CLIENT_OK.]
  TEST_FUNCTION(SetOption_xio_option_success)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      bool value = true;
  
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE))
          .SetReturn(TEST_IOTHUB_HOST_FQDN_CHAR_PTR);
      STRICT_EXPECTED_CALL(xio_setoption(TEST_UNDERLYING_IO_TRANSPORT, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
          .IgnoreArgument(2)
          .IgnoreArgument(3)
          .SetReturn(0);
      STRICT_EXPECTED_CALL(xio_retrieveoptions(TEST_UNDERLYING_IO_TRANSPORT))
          .SetReturn(TEST_OPTIONHANDLER_HANDLE);
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "Some XIO option name", &value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_107: [If instance->underlying_io_transport_provider() fails, IoTHubTransport_AMQP_Common_SetOption shall fail and return IOTHUB_CLIENT_ERROR]
  TEST_FUNCTION(SetOption_xio_option_get_underlying_TLS_fails)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      bool value = true;
      TEST_amqp_get_io_transport_result = NULL;
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE))
          .SetReturn(TEST_IOTHUB_HOST_FQDN_CHAR_PTR);
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "Some XIO option name", &value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_03_001: [If xio_setoption fails, IoTHubTransport_AMQP_Common_SetOption shall return IOTHUB_CLIENT_ERROR.]
  TEST_FUNCTION(SetOption_xio_option_fails)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      bool value = true;
  
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE))
          .SetReturn(TEST_IOTHUB_HOST_FQDN_CHAR_PTR);
      STRICT_EXPECTED_CALL(xio_setoption(TEST_UNDERLYING_IO_TRANSPORT, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
          .SetReturn(1);
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "Some XIO option name", &value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_99_002: [If `OPTION_AMQP_REMOTE_IDLE_TIMEOUT_RATIO` value is 0, the test will fail]
  TEST_FUNCTION(SetOption_cl2svc_keep_alive_send_ratio_fail_for_zero)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      // This creates the amqp_connection_handle
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      double value = 0.0;
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_REMOTE_IDLE_TIMEOUT_RATIO, &value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_99_003: [If `OPTION_AMQP_REMOTE_IDLE_TIMEOUT_RATIO` value is 1, the test will fail]
  TEST_FUNCTION(SetOption_cl2svc_keep_alive_send_ratio_fail_for_1)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      // This creates the amqp_connection_handle
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      double value = 1.0;
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_REMOTE_IDLE_TIMEOUT_RATIO, &value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_99_004: [If `OPTION_AMQP_REMOTE_IDLE_TIMEOUT_RATIO` value is 0.875, the test will succeed]
  TEST_FUNCTION(SetOption_cl2svc_keep_alive_send_ratio_success_for_0875)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      // This creates the amqp_connection_handle
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      double value = 0.875;
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_REMOTE_IDLE_TIMEOUT_RATIO, &value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_032: [ If `option` is `proxy_data`, `value` shall be used as an `HTTP_PROXY_OPTIONS*`. ]*/
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_033: [ The fields `host_address`, `port`, `username` and `password` shall be saved for later used (needed when creating the underlying IO to be used by the transport). ]*/
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_039: [ If setting the `proxy_data` option succeeds, `IoTHubTransport_AMQP_Common_SetOption` shall return `IOTHUB_CLIENT_OK` ]*/
  TEST_FUNCTION(SetOption_with_proxy_data_copies_the_options_for_later_use)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "me";
      http_proxy_options.password = "shhhh";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "me"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.username, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "shhhh"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.password, sizeof(char**));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_034: [ If `host_address` is NULL, `IoTHubTransport_AMQP_Common_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
  TEST_FUNCTION(SetOption_proxy_data_with_NULL_host_address_fails)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = NULL;
      http_proxy_options.port = 2222;
      http_proxy_options.username = "me";
      http_proxy_options.password = "shhhh";
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_101: [If `handle`, `option` or `value` are NULL then IoTHubTransport_AMQP_Common_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]*/
  TEST_FUNCTION(SetOption_proxy_data_with_NULL_option_value_fails)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", NULL);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_036: [ `username` and `password` shall be allowed to be NULL. ]*/
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_039: [ If setting the `proxy_data` option succeeds, `IoTHubTransport_AMQP_Common_SetOption` shall return `IOTHUB_CLIENT_OK` ]*/
  TEST_FUNCTION(SetOption_proxy_data_with_NULL_username_and_password_saves_only_the_hostname)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = NULL;
      http_proxy_options.password = NULL;
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_037: [ If only one of `username` and `password` is NULL, `IoTHubTransport_AMQP_Common_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
  TEST_FUNCTION(SetOption_proxy_data_with_NULL_username_but_non_NULL_password_fails)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "the_other_me";
      http_proxy_options.password = NULL;
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_037: [ If only one of `username` and `password` is NULL, `IoTHubTransport_AMQP_Common_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
  TEST_FUNCTION(SetOption_proxy_data_with_NULL_password_but_non_NULL_username_fails)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = NULL;
      http_proxy_options.password = "bleah";
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_040: [ When setting the proxy options succeeds any previously saved proxy options shall be freed. ]*/
  TEST_FUNCTION(SetOption_proxy_data_frees_previously_Saved_proxy_options)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.username, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "bleah"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.password, sizeof(char**));
  
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "me"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.username, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "shhhh"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.password, sizeof(char**));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "me";
      http_proxy_options.password = "shhhh";
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_035: [ If copying `host_address`, `username` or `password` fails, `IoTHubTransport_AMQP_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
  TEST_FUNCTION(when_allocating_proxy_name_fails_SetOption_proxy_data_fails)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .SetReturn(1);
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_035: [ If copying `host_address`, `username` or `password` fails, `IoTHubTransport_AMQP_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
  TEST_FUNCTION(when_allocating_username_fails_SetOption_proxy_data_fails)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .SetReturn(1);
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_035: [ If copying `host_address`, `username` or `password` fails, `IoTHubTransport_AMQP_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
  TEST_FUNCTION(when_allocating_password_fails_SetOption_proxy_data_fails)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "bleah"))
          .SetReturn(1);
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_040: [ When setting the proxy options succeeds any previously saved proxy options shall be freed. ]*/
  TEST_FUNCTION(when_allocating_proxy_name_fails_SetOption_proxy_data_does_not_free_previous_proxy_options)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.username, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "bleah"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.password, sizeof(char**));
  
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .SetReturn(1);
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_040: [ When setting the proxy options succeeds any previously saved proxy options shall be freed. ]*/
  TEST_FUNCTION(when_allocating_username_fails_SetOption_proxy_data_does_not_free_previous_proxy_options)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.username, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "bleah"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.password, sizeof(char**));
  
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .SetReturn(1);
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_040: [ When setting the proxy options succeeds any previously saved proxy options shall be freed. ]*/
  TEST_FUNCTION(when_allocating_password_fails_SetOption_proxy_data_does_not_free_previous_proxy_options)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.username, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "bleah"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.password, sizeof(char**));
  
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "bleah"))
          .SetReturn(1);
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_040: [ When setting the proxy options succeeds any previously saved proxy options shall be freed. ]*/
  TEST_FUNCTION(SetOption_proxy_data_with_NULL_hostname_does_not_free_previous_proxy_options)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.username, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "bleah"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.password, sizeof(char**));
  
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = NULL;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_040: [ When setting the proxy options succeeds any previously saved proxy options shall be freed. ]*/
  TEST_FUNCTION(SetOption_proxy_data_with_NULL_username_and_non_NULL_password_does_not_free_previous_proxy_options)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.username, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "bleah"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.password, sizeof(char**));
  
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "baba";
      http_proxy_options.username = NULL;
      http_proxy_options.password = "cloanta";
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_042: [ If no `proxy_data` option has been set, NULL shall be passed as the argument `amqp_transport_proxy_options` when calling the function `underlying_io_transport_provider()`. ]*/
  TEST_FUNCTION(SetOption_xio_option_get_underlying_TLS_when_proxy_data_was_not_set_passes_down_NULL)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      bool value = true;
      TEST_amqp_get_io_transport_result = NULL;
      expected_AMQP_TRANSPORT_PROXY_OPTIONS = NULL;
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "Some XIO option name", &value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(int, 0, error_proxy_options);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_041: [ If the `proxy_data` option has been set, the proxy options shall be filled in the argument `amqp_transport_proxy_options` when calling the function `underlying_io_transport_provider()` to obtain the underlying IO handle. ]*/
  TEST_FUNCTION(SetOption_xio_option_get_underlying_TLS_when_proxy_data_was_set_passes_down_the_proxy_options)
  {
      // arrange
      AMQP_TRANSPORT_PROXY_OPTIONS amqp_transport_proxy_options;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.username, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "bleah"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.password, sizeof(char**));
  
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      amqp_transport_proxy_options.host_address = "test_proxy";
      amqp_transport_proxy_options.port = 2222;
      amqp_transport_proxy_options.username = "haha";
      amqp_transport_proxy_options.password = "bleah";
  
      bool value = true;
      TEST_amqp_get_io_transport_result = NULL;
      expected_AMQP_TRANSPORT_PROXY_OPTIONS = &amqp_transport_proxy_options;
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "Some XIO option name", &value);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(int, 0, error_proxy_options);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_038: [ If the underlying IO has already been created, then `IoTHubTransport_AMQP_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
  TEST_FUNCTION(SetOption_proxy_data_when_underlying_IO_is_already_created_fails)
  {
      // arrange
      AMQP_TRANSPORT_PROXY_OPTIONS amqp_transport_proxy_options;
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      amqp_transport_proxy_options.host_address = "test_proxy";
      amqp_transport_proxy_options.port = 2222;
      amqp_transport_proxy_options.username = "haha";
      amqp_transport_proxy_options.password = "bleah";
  
      bool value = true;
      expected_AMQP_TRANSPORT_PROXY_OPTIONS = &amqp_transport_proxy_options;
  
      // act
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, "Some XIO option name", &value);
      umock_c_reset_all_calls();
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
  
      // assert
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  TEST_FUNCTION(SetOption_retry_interval_succeed)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      // act
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(retry_control_set_option(IGNORED_PTR_ARG, RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, IGNORED_PTR_ARG));
  
      int retry_interval = 10;
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_RETRY_INTERVAL_SEC, &retry_interval);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  TEST_FUNCTION(SetOption_retry_interval_fail)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      // act
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(retry_control_set_option(IGNORED_PTR_ARG, RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, IGNORED_PTR_ARG)).SetReturn(__LINE__);
  
      int retry_interval = 10;
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_RETRY_INTERVAL_SEC, &retry_interval);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_043: [ `IoTHubTransport_AMQP_Common_Destroy` shall free the stored proxy options. ]*/
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_Destroy_frees_proxy_options)
  {
      // arrange
      HTTP_PROXY_OPTIONS http_proxy_options;
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      http_proxy_options.host_address = "test_proxy";
      http_proxy_options.port = 2222;
      http_proxy_options.username = "haha";
      http_proxy_options.password = "bleah";
  
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "test_proxy"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.host_address, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "haha"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.username, sizeof(char**));
      STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, "bleah"))
          .CopyOutArgumentBuffer_destination(&http_proxy_options.password, sizeof(char**));
  
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, "proxy_data", &http_proxy_options);
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(TEST_REGISTERED_DEVICES_LIST));
  
      EXPECTED_CALL(singlylinkedlist_item_get_value(IGNORED_PTR_ARG));
      EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_PTR_ARG));
  
      set_expected_calls_for_Unregister(device_handle);
  
      STRICT_EXPECTED_CALL(singlylinkedlist_destroy(TEST_REGISTERED_DEVICES_LIST));
      STRICT_EXPECTED_CALL(retry_control_destroy(TEST_RETRY_CONTROL_HANDLE));
      STRICT_EXPECTED_CALL(STRING_delete(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IoTHubTransport_AMQP_Common_Destroy(handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_079: [if `deviceHandle` provided is NULL, IoTHubTransport_AMQP_Common_Unregister shall return.]
  TEST_FUNCTION(Unregister_NULL_handle)
  {
      // arrange
      initialize_test_variables();
      umock_c_reset_all_calls();
  
      // act
      IoTHubTransport_AMQP_Common_Unregister(NULL);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_081: [If the device is not registered with this transport, IoTHubTransport_AMQP_Common_Unregister shall return]
  TEST_FUNCTION(Unregister_device_not_registered)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_DEVICE_ID_STRING_HANDLE))
          .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
      set_expected_calls_for_is_device_registered_ex(device_config, NULL);
  
      // act
      IoTHubTransport_AMQP_Common_Unregister(device_handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_080: [if `deviceHandle` has a NULL reference to its transport instance, IoTHubTransport_AMQP_Common_Unregister shall return.] (NT)
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_082: [`device_instance` shall be removed from `instance->registered_devices`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_01_012: [IoTHubTransport_AMQP_Common_Unregister shall destroy the C2D methods handler by calling iothubtransportamqp_methods_destroy]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_083: [IoTHubTransport_AMQP_Common_Unregister shall free all the memory allocated for the `device_instance`]
  TEST_FUNCTION(Unregister_succeeds)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Unregister(device_handle);
  
      // act
      IoTHubTransport_AMQP_Common_Unregister(device_handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_089: [IoTHubClientCore_LL_MessageCallback() shall be invoked passing the client and the incoming message handles as parameters]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_091: [If IoTHubClientCore_LL_MessageCallback() succeeds, on_message_received_callback shall return DEVICE_MESSAGE_DISPOSITION_RESULT_NONE]
  TEST_FUNCTION(on_message_received_succeeds)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Subscribe(device_config, device_handle);
      (void)IoTHubTransport_AMQP_Common_Subscribe(device_handle);
  
      DEVICE_MESSAGE_DISPOSITION_INFO disposition_info;
      disposition_info.source = "some link source name";
      disposition_info.message_id = TEST_MESSAGE_ID;
  
      umock_c_reset_all_calls();
      EXPECTED_CALL(malloc(IGNORED_NUM_ARG));
      EXPECTED_CALL(malloc(IGNORED_NUM_ARG));
      EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, IGNORED_PTR_ARG));
      g_MessageCallback_return = true;
      STRICT_EXPECTED_CALL(Transport_MessageCallback(IGNORED_PTR_ARG, IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      DEVICE_MESSAGE_DISPOSITION_RESULT result = TEST_device_subscribe_message_saved_callback(
          TEST_IOTHUB_MESSAGE_HANDLE, &disposition_info, TEST_device_subscribe_message_saved_context);
  
      // assert
      ASSERT_ARE_EQUAL(int, DEVICE_MESSAGE_DISPOSITION_RESULT_NONE, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_090: [If IoTHubClientCore_LL_MessageCallback() fails, on_message_received_callback shall return DEVICE_MESSAGE_DISPOSITION_RESULT_RELEASED]
  TEST_FUNCTION(on_message_received_fails)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_Subscribe(device_config, device_handle);
      (void)IoTHubTransport_AMQP_Common_Subscribe(device_handle);
  
      DEVICE_MESSAGE_DISPOSITION_INFO disposition_info;
      disposition_info.source = "some link source name";
      disposition_info.message_id = TEST_MESSAGE_ID;
  
      umock_c_reset_all_calls();
      EXPECTED_CALL(malloc(IGNORED_NUM_ARG));
      EXPECTED_CALL(malloc(IGNORED_NUM_ARG));
      EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, IGNORED_PTR_ARG));
      g_MessageCallback_return = false;
      STRICT_EXPECTED_CALL(Transport_MessageCallback(IGNORED_PTR_ARG, IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(IoTHubMessage_Destroy(TEST_IOTHUB_MESSAGE_HANDLE));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      DEVICE_MESSAGE_DISPOSITION_RESULT result = TEST_device_subscribe_message_saved_callback(
          TEST_IOTHUB_MESSAGE_HANDLE, &disposition_info, TEST_device_subscribe_message_saved_context);
  
      // assert
      ASSERT_ARE_EQUAL(int, DEVICE_MESSAGE_DISPOSITION_RESULT_RELEASED, result);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_019: [If `instance->amqp_connection` is NULL, it shall be established]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_020: [If the amqp_connection is OPENED, the transport shall iterate through each registered device and perform a device-specific do_work on each]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_022: [If `instance->amqp_connection` is not NULL, amqp_connection_do_work shall be invoked]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_023: [If `instance->tls_io` is NULL, it shall be set invoking instance->underlying_io_transport_provider()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_026: [If `transport->connection` is NULL, it shall be created using amqp_connection_create()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_029: [`instance->is_trace_on` shall be set into `AMQP_CONNECTION_CONFIG->is_trace_on`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_110: [If amqp_connection_create() succeeds, IoTHubTransport_AMQP_Common_DoWork shall proceed to invoke amqp_connection_do_work]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_036: [If the device state is DEVICE_STATE_STOPPED, it shall be started]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_037: [If transport is using CBS authentication, amqp_connection_get_cbs_handle() shall be invoked on `instance->connection`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_039: [amqp_connection_get_session_handle() shall be invoked on `instance->connection`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_040: [If amqp_connection_get_session_handle() fails, IoTHubTransport_AMQP_Common_DoWork shall fail and return]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_041: [The device handle shall be started using amqp_device_start_async()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_059: [`new_state` shall be saved in to the transport instance]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_061: [If `new_state` is the same as `previous_state`, on_device_state_changed_callback shall return]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_062: [If `new_state` shall be saved into the `registered_device` instance]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_063: [If `registered_device->time_of_last_state_change` shall be set using get_time()]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_120: [If `new_state` is DEVICE_STATE_STARTED, IoTHubClientCore_LL_ConnectionStatusCallBack shall be invoked with IOTHUB_CLIENT_CONNECTION_AUTHENTICATED and IOTHUB_CLIENT_CONNECTION_OK]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_127: [If `new_state` is DEVICE_STATE_STARTED, retry_control_reset() shall be invoked passing `instance->connection_retry_control`]
  TEST_FUNCTION(DoWork_success)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      // act
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STOPPED, false, true, false, false, 1, TEST_current_time, false);
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      ASSERT_IS_NOT_NULL(TEST_amqp_connection_create_saved_on_state_changed_callback);
  
      TEST_amqp_connection_create_saved_on_state_changed_callback(
          TEST_amqp_connection_create_saved_on_state_changed_context,
          AMQP_CONNECTION_STATE_CLOSED, AMQP_CONNECTION_STATE_OPENED);
  
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STOPPED, true, true, true, true, 1, TEST_current_time, false);
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      ASSERT_IS_NOT_NULL(TEST_device_create_saved_on_state_changed_callback);
  
      STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(TEST_current_time);
      STRICT_EXPECTED_CALL(retry_control_reset(TEST_RETRY_CONTROL_HANDLE));
      STRICT_EXPECTED_CALL(Transport_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_AUTHENTICATED, IOTHUB_CLIENT_CONNECTION_OK, IGNORED_PTR_ARG));
  
      TEST_device_create_saved_on_state_changed_callback(TEST_device_create_saved_on_state_changed_context,
          DEVICE_STATE_STOPPED, DEVICE_STATE_STARTED);
  
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STARTED, true, true, true, true, 1, TEST_current_time, false);
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_115: [If the AMQP connection is closed by the service side, the connection retry logic shall be triggered]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_126: [The connection retry shall be attempted only if retry_control_should_retry() returns RETRY_ACTION_NOW, or if it fails]
  TEST_FUNCTION(on_amqp_connection_state_changed_CLOSED_unexpectedly)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
  
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STOPPED, false, true, false, false, 1, TEST_current_time, false);
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      TEST_amqp_connection_create_saved_on_state_changed_callback(
          TEST_amqp_connection_create_saved_on_state_changed_context,
          AMQP_CONNECTION_STATE_CLOSED, AMQP_CONNECTION_STATE_OPENED);
  
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STOPPED, true, true, true, true, 1, TEST_current_time, false);
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // act
      TEST_amqp_connection_create_saved_on_state_changed_callback(
          TEST_amqp_connection_create_saved_on_state_changed_context,
          AMQP_CONNECTION_STATE_OPENED, AMQP_CONNECTION_STATE_CLOSED);
  
      set_expected_calls_for_prepare_for_connection_retry(1, DEVICE_STATE_STOPPED);
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      set_expected_calls_for_DoWork2(&TEST_waitingToSend, 0, DEVICE_STATE_STOPPED, false, true, true, false, false, 1, TEST_current_time, false);
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_016: [If `handle` is NULL, IoTHubTransport_AMQP_Common_DoWork shall return without doing any work]
  TEST_FUNCTION(DoWork_NULL_handle)
  {
      // arrange
      initialize_test_variables();
      umock_c_reset_all_calls();
  
      // act
      IoTHubTransport_AMQP_Common_DoWork(NULL);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_024: [If instance->underlying_io_transport_provider() fails, IoTHubTransport_AMQP_Common_DoWork shall fail and return]
  TEST_FUNCTION(DoWork_get_underlying_io_transport_provider_fails)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(TEST_REGISTERED_DEVICES_LIST));
      STRICT_EXPECTED_CALL(STRING_c_str(TEST_IOTHUB_HOST_FQDN_STRING_HANDLE))
          .SetReturn(TEST_IOTHUB_HOST_FQDN_CHAR_PTR);
      TEST_amqp_get_io_transport_result = NULL;
  
      // act
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_028: [If `transport->preferred_credential_method` is X509, AMQP_CONNECTION_CONFIG shall be set with `create_sasl_io` = false and `create_cbs_connection` = false]
  TEST_FUNCTION(DoWork_sets_amqp_connection_for_X509)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      const char* certificate = TEST_X509_CERTIFICATE;
      const char* private_key = TEST_X509_PRIVATE_KEY;
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_X509_CERT, certificate);
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_X509_PRIVATE_KEY, private_key);
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config_for_x509(TEST_DEVICE_ID_CHAR_PTR);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, false);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STOPPED, true, true, false, false, 1, TEST_current_time, false);
  
      // act
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // assert
      ASSERT_IS_FALSE(TEST_amqp_connection_create_saved_create_sasl_io);
      ASSERT_IS_FALSE(TEST_amqp_connection_create_saved_create_cbs_connection);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(size_t, TEST_amqp_connection_create_saved_c2d_keep_alive_freq_secs, TEST_DEFAULT_SVC2CL_KEEP_ALIVE_FREQ_SECS);
      ASSERT_ARE_EQUAL(double, TEST_amqp_connection_create_saved_cl2svc_keep_alive_send_ratio, TEST_DEFAULT_REMOTE_IDLE_TIMEOUT_RATIO);
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_027: [If `transport->preferred_authentication_method` is CBS, AMQP_CONNECTION_CONFIG shall be set with `create_sasl_io` = true and `create_cbs_connection` = true]
  TEST_FUNCTION(DoWork_sets_amqp_connection_for_CBS)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, false);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STOPPED, false, true, false, false, 1, TEST_current_time, false);
  
      // act
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // assert
      ASSERT_IS_TRUE(TEST_amqp_connection_create_saved_create_sasl_io);
      ASSERT_IS_TRUE(TEST_amqp_connection_create_saved_create_cbs_connection);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(size_t, TEST_amqp_connection_create_saved_c2d_keep_alive_freq_secs, TEST_DEFAULT_SVC2CL_KEEP_ALIVE_FREQ_SECS);
      ASSERT_ARE_EQUAL(double, TEST_amqp_connection_create_saved_cl2svc_keep_alive_send_ratio, TEST_DEFAULT_REMOTE_IDLE_TIMEOUT_RATIO);
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_12_003: [AMQP connection will be configured using the `c2d_keep_alive_freq_secs` value from SetOption ]
  TEST_FUNCTION(DoWork_configures_AMQP_connection_using_c2d_keep_alive_freq_secs)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      const char* certificate = TEST_X509_CERTIFICATE;
      const char* private_key = TEST_X509_PRIVATE_KEY;
      size_t c2d_secs = TEST_USER_SVC2CL_KEEP_ALIVE_FREQ_SECS;
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_X509_CERT, certificate);
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_X509_PRIVATE_KEY, private_key);
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_SERVICE_SIDE_KEEP_ALIVE_FREQ_SECS, &c2d_secs);
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config_for_x509(TEST_DEVICE_ID_CHAR_PTR);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, false);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STOPPED, true, true, false, false, 1, TEST_current_time, false);
  
      // act
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // assert
      ASSERT_IS_FALSE(TEST_amqp_connection_create_saved_create_sasl_io);
      ASSERT_IS_FALSE(TEST_amqp_connection_create_saved_create_cbs_connection);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(size_t, TEST_amqp_connection_create_saved_c2d_keep_alive_freq_secs, TEST_USER_SVC2CL_KEEP_ALIVE_FREQ_SECS);
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_99_001: [AMQP connection will be configured using the `cl2svc_keep_alive_send_ratio` value from SetOption ]
  TEST_FUNCTION(DoWork_configures_AMQP_connection_using_cl2svc_keep_alive_send_ratio)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      const char* certificate = TEST_X509_CERTIFICATE;
      const char* private_key = TEST_X509_PRIVATE_KEY;
      double cl2svc_ratio = TEST_USER_REMOTE_IDLE_TIMEOUT_RATIO;
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_X509_CERT, certificate);
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_X509_PRIVATE_KEY, private_key);
      (void)IoTHubTransport_AMQP_Common_SetOption(handle, OPTION_REMOTE_IDLE_TIMEOUT_RATIO, &cl2svc_ratio);
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config_for_x509(TEST_DEVICE_ID_CHAR_PTR);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, false);
      ASSERT_IS_NOT_NULL(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_DoWork(&TEST_waitingToSend, 0, DEVICE_STATE_STOPPED, true, true, false, false, 1, TEST_current_time, false);
  
      // act
      IoTHubTransport_AMQP_Common_DoWork(handle);
  
      // assert
      ASSERT_IS_FALSE(TEST_amqp_connection_create_saved_create_sasl_io);
      ASSERT_IS_FALSE(TEST_amqp_connection_create_saved_create_cbs_connection);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(double, TEST_amqp_connection_create_saved_cl2svc_keep_alive_send_ratio, TEST_USER_REMOTE_IDLE_TIMEOUT_RATIO);
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_121: [If `new_state` is DEVICE_STATE_STOPPED, IoTHubClientCore_LL_ConnectionStatusCallBack shall be invoked with IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED and IOTHUB_CLIENT_CONNECTION_OK]
  TEST_FUNCTION(ConnectionStatusCallBack_UNAUTH_OK)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE device_handle;
      device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(TEST_current_time);
      STRICT_EXPECTED_CALL(Transport_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_OK, IGNORED_PTR_ARG));
  
      // act
      TEST_device_create_saved_on_state_changed_callback(TEST_device_create_saved_on_state_changed_context,
          DEVICE_STATE_STARTED, DEVICE_STATE_STOPPED);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_122: [If `new_state` is DEVICE_STATE_ERROR_AUTH, IoTHubClientCore_LL_ConnectionStatusCallBack shall be invoked with IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED and IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL]
  TEST_FUNCTION(ConnectionStatusCallBack_UNAUTH_auth_error)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE device_handle;
      device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(TEST_current_time);
      STRICT_EXPECTED_CALL(Transport_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL, IGNORED_PTR_ARG));
  
      // act
      TEST_device_create_saved_on_state_changed_callback(TEST_device_create_saved_on_state_changed_context,
          DEVICE_STATE_STARTED, DEVICE_STATE_ERROR_AUTH);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_123: [If `new_state` is DEVICE_STATE_ERROR_AUTH_TIMEOUT or DEVICE_STATE_ERROR_MSG, IoTHubClientCore_LL_ConnectionStatusCallBack shall be invoked with IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED and IOTHUB_CLIENT_CONNECTION_COMMUNICATION_ERROR]
  TEST_FUNCTION(ConnectionStatusCallBack_UNAUTH_auth_communication_error)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE device_handle;
      device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(TEST_current_time);
      STRICT_EXPECTED_CALL(Transport_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_COMMUNICATION_ERROR, IGNORED_PTR_ARG));
  
      // act
      TEST_device_create_saved_on_state_changed_callback(TEST_device_create_saved_on_state_changed_context,
          DEVICE_STATE_STARTED, DEVICE_STATE_ERROR_AUTH_TIMEOUT);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_123: [If `new_state` is DEVICE_STATE_ERROR_AUTH_TIMEOUT or DEVICE_STATE_ERROR_MSG, IoTHubClientCore_LL_ConnectionStatusCallBack shall be invoked with IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED and IOTHUB_CLIENT_CONNECTION_COMMUNICATION_ERROR]
  TEST_FUNCTION(ConnectionStatusCallBack_UNAUTH_msg_communication_error)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE device_handle;
      device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(TEST_current_time);
      STRICT_EXPECTED_CALL(Transport_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_COMMUNICATION_ERROR, IGNORED_PTR_ARG));
  
      // act
      TEST_device_create_saved_on_state_changed_callback(TEST_device_create_saved_on_state_changed_context,
          DEVICE_STATE_STARTED, DEVICE_STATE_ERROR_MSG);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  TEST_FUNCTION(ConnectionStatusCallBack_UNAUTH_no_network)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE device_handle;
      device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(Transport_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_NO_NETWORK, IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(get_time(NULL)).SetReturn(TEST_current_time);
  
      // act
  
      TEST_amqp_connection_create_saved_on_state_changed_callback(
          TEST_amqp_connection_create_saved_on_state_changed_context,
          AMQP_CONNECTION_STATE_OPENED, AMQP_CONNECTION_STATE_ERROR);
  
      TEST_device_create_saved_on_state_changed_callback(TEST_device_create_saved_on_state_changed_context,
          DEVICE_STATE_STARTED, DEVICE_STATE_STOPPED);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  TEST_FUNCTION(ConnectionStatusCallBack_UNAUTH_retry_expired)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
      int result_set_retry_policy = IoTHubTransport_AMQP_Common_SetRetryPolicy(handle, IOTHUB_CLIENT_RETRY_IMMEDIATE, 1);
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE device_handle;
      device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(Transport_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_NO_NETWORK, IGNORED_PTR_ARG));
      RETRY_ACTION retry_action = RETRY_ACTION_STOP_RETRYING;
      STRICT_EXPECTED_CALL(retry_control_should_retry(TEST_RETRY_CONTROL_HANDLE, IGNORED_PTR_ARG))
          .CopyOutArgumentBuffer_retry_action(&retry_action, sizeof(RETRY_ACTION));
  
      STRICT_EXPECTED_CALL(singlylinkedlist_foreach(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG));
  
      STRICT_EXPECTED_CALL(Transport_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_RETRY_EXPIRED, IGNORED_PTR_ARG));
  
      // act
      TEST_amqp_connection_create_saved_on_state_changed_callback(
          TEST_amqp_connection_create_saved_on_state_changed_context,
          AMQP_CONNECTION_STATE_OPENED, AMQP_CONNECTION_STATE_ERROR);
  
      (void)IoTHubTransport_AMQP_Common_DoWork(handle);
  
      bool continue_processing;
      TEST_singlylinkedlist_foreach_action_function(
          saved_registered_devices_list[saved_registered_devices_list_count - 1],
          TEST_singlylinkedlist_foreach_context,
          &continue_processing);
  
      // assert
      ASSERT_ARE_EQUAL(int, 0, result_set_retry_policy);
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
  
      // cleanup
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_10_001: [ If messageData is NULL, IoTHubTransport_AMQP_Common_SendMessageDisposition shall fail and return IOTHUB_CLIENT_INVALID_ARG. ] */
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SendMessageDisposition_NULL_data_fails)
  {
      // arrange
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SendMessageDisposition(NULL, IOTHUBMESSAGE_ACCEPTED);
  
      //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());
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_10_002: [If any of the messageData fields are NULL, IoTHubTransport_AMQP_Common_SendMessageDisposition shall fail and return IOTHUB_CLIENT_INVALID_ARG. ] */
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SendMessageDisposition_NULL_MESSAGE_fails)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, false);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      MESSAGE_CALLBACK_INFO* data = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
      memset(data, 0, sizeof(MESSAGE_CALLBACK_INFO));
      data->messageHandle = NULL;
      data->transportContext = TRANSPORT_CONTEXT_DATA_create2(device_handle);
  
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SendMessageDisposition(data, IOTHUBMESSAGE_ACCEPTED);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_10_002: [If any of the messageData fields are NULL, IoTHubTransport_AMQP_Common_SendMessageDisposition shall fail and return IOTHUB_CLIENT_INVALID_ARG. ] */
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SendMessageDisposition_NULL_CONTEXT_fails)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, false);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      MESSAGE_CALLBACK_INFO* data = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
      memset(data, 0, sizeof(MESSAGE_CALLBACK_INFO));
      data->messageHandle = TEST_IOTHUB_MESSAGE_HANDLE;
      data->transportContext = NULL;
  
      umock_c_reset_all_calls();
  
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SendMessageDisposition(data, IOTHUBMESSAGE_ACCEPTED);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_10_004: [IoTHubTransport_AMQP_Common_SendMessageDisposition shall convert the given IOTHUBMESSAGE_DISPOSITION_RESULT to the equivalent DEVICE_MESSAGE_DISPOSITION_RESULT and send it via amqp_device_send_message_disposition.]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_112: [A DEVICE_MESSAGE_DISPOSITION_INFO instance shall be created with a copy of the `link_name` and `message_id` contained in `message_data`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_114: [`IoTHubTransport_AMQP_Common_SendMessageDisposition()` shall destroy the DEVICE_MESSAGE_DISPOSITION_INFO instance]
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SendMessageDisposition_ACCEPTED_succeeds)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, false);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      MESSAGE_CALLBACK_INFO* data = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
      memset(data, 0, sizeof(MESSAGE_CALLBACK_INFO));
      data->messageHandle = TEST_IOTHUB_MESSAGE_HANDLE;
      data->transportContext = TRANSPORT_CONTEXT_DATA_create2(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_SendMessageDisposition(IOTHUBMESSAGE_ACCEPTED);
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SendMessageDisposition(data, IOTHUBMESSAGE_ACCEPTED);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_10_004: [IoTHubTransport_AMQP_Common_SendMessageDisposition shall convert the given IOTHUBMESSAGE_DISPOSITION_RESULT to the equivalent AMQP_VALUE and will return the result of calling messagereceiver_send_message_disposition. ] */
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SendMessageDisposition_ACCEPTED_fails)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, false);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      MESSAGE_CALLBACK_INFO* data = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
      memset(data, 0, sizeof(MESSAGE_CALLBACK_INFO));
      data->messageHandle = TEST_IOTHUB_MESSAGE_HANDLE;
      data->transportContext = TRANSPORT_CONTEXT_DATA_create2(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_create_device_message_disposition_info();
      STRICT_EXPECTED_CALL(amqp_device_send_message_disposition(TEST_DEVICE_HANDLE, IGNORED_PTR_ARG, DEVICE_MESSAGE_DISPOSITION_RESULT_ACCEPTED))
          .IgnoreArgument(2)
          .SetReturn(1);
      EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG))
          .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
      set_expected_calls_for_destroy_device_message_disposition_info();
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SendMessageDisposition(data, IOTHUBMESSAGE_ACCEPTED);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_113: [If the DEVICE_MESSAGE_DISPOSITION_INFO fails to be created, `IoTHubTransport_AMQP_Common_SendMessageDisposition()` shall fail and return IOTHUB_CLIENT_ERROR]
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SendMessageDisposition_DEVICE_MESSAGE_DISPOSITION_INFO_create_fails)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, false);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      MESSAGE_CALLBACK_INFO* data = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
      memset(data, 0, sizeof(MESSAGE_CALLBACK_INFO));
      data->messageHandle = TEST_IOTHUB_MESSAGE_HANDLE;
      data->transportContext = TRANSPORT_CONTEXT_DATA_create2(device_handle);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(malloc(sizeof(DEVICE_MESSAGE_DISPOSITION_INFO)))
          .SetReturn(NULL);
      EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG))
          .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SendMessageDisposition(data, IOTHUBMESSAGE_ACCEPTED);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_10_004: [IoTHubTransport_AMQP_Common_SendMessageDisposition shall convert the given IOTHUBMESSAGE_DISPOSITION_RESULT to the equivalent AMQP_VALUE and will return the result of calling messagereceiver_send_message_disposition. ] */
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SendMessageDisposition_ABANDONED_succeeds)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, false);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      MESSAGE_CALLBACK_INFO* data = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
      memset(data, 0, sizeof(MESSAGE_CALLBACK_INFO));
      data->messageHandle = TEST_IOTHUB_MESSAGE_HANDLE;
      data->transportContext = TRANSPORT_CONTEXT_DATA_create2(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_SendMessageDisposition(IOTHUBMESSAGE_ABANDONED);
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SendMessageDisposition(data, IOTHUBMESSAGE_ABANDONED);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_10_004: [IoTHubTransport_AMQP_Common_SendMessageDisposition shall convert the given IOTHUBMESSAGE_DISPOSITION_RESULT to the equivalent AMQP_VALUE and will return the result of calling messagereceiver_send_message_disposition. ] */
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SendMessageDisposition_ABANDONED_fails)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, false);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      MESSAGE_CALLBACK_INFO* data = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
      memset(data, 0, sizeof(MESSAGE_CALLBACK_INFO));
      data->messageHandle = TEST_IOTHUB_MESSAGE_HANDLE;
      data->transportContext = TRANSPORT_CONTEXT_DATA_create2(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_create_device_message_disposition_info();
      STRICT_EXPECTED_CALL(amqp_device_send_message_disposition(TEST_DEVICE_HANDLE, IGNORED_PTR_ARG, DEVICE_MESSAGE_DISPOSITION_RESULT_RELEASED))
          .IgnoreArgument(2)
          .SetReturn(1);
      EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG))
          .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
      set_expected_calls_for_destroy_device_message_disposition_info();
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SendMessageDisposition(data, IOTHUBMESSAGE_ABANDONED);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_10_004: [IoTHubTransport_AMQP_Common_SendMessageDisposition shall convert the given IOTHUBMESSAGE_DISPOSITION_RESULT to the equivalent AMQP_VALUE and will return the result of calling messagereceiver_send_message_disposition. ] */
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SendMessageDisposition_REJECTED_succeeds)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, false);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      MESSAGE_CALLBACK_INFO* data = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
      memset(data, 0, sizeof(MESSAGE_CALLBACK_INFO));
      data->messageHandle = TEST_IOTHUB_MESSAGE_HANDLE;
      data->transportContext = TRANSPORT_CONTEXT_DATA_create2(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_SendMessageDisposition(IOTHUBMESSAGE_REJECTED);
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SendMessageDisposition(data, IOTHUBMESSAGE_REJECTED);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  /* Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_10_004: [IoTHubTransport_AMQP_Common_SendMessageDisposition shall convert the given IOTHUBMESSAGE_DISPOSITION_RESULT to the equivalent AMQP_VALUE and will return the result of calling messagereceiver_send_message_disposition. ] */
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SendMessageDisposition_REJECTED_fails)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, false);
      IOTHUB_DEVICE_HANDLE device_handle = register_device(handle, device_config, &TEST_waitingToSend, true);
      ASSERT_IS_NOT_NULL(device_handle);
  
      MESSAGE_CALLBACK_INFO* data = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
      memset(data, 0, sizeof(MESSAGE_CALLBACK_INFO));
      data->messageHandle = TEST_IOTHUB_MESSAGE_HANDLE;
      data->transportContext = TRANSPORT_CONTEXT_DATA_create2(device_handle);
  
      umock_c_reset_all_calls();
      set_expected_calls_for_create_device_message_disposition_info();
      STRICT_EXPECTED_CALL(amqp_device_send_message_disposition(TEST_DEVICE_HANDLE, IGNORED_PTR_ARG, DEVICE_MESSAGE_DISPOSITION_RESULT_REJECTED))
          .IgnoreArgument(2)
          .SetReturn(1);
      EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG))
          .SetReturn(TEST_DEVICE_ID_CHAR_PTR);
      set_expected_calls_for_destroy_device_message_disposition_info();
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
      STRICT_EXPECTED_CALL(free(IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_SendMessageDisposition(data, IOTHUBMESSAGE_REJECTED);
  
      // 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
      destroy_transport(handle, device_handle, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_128: [If `handle` is NULL, `IoTHubTransport_AMQP_Common_SetRetryPolicy` shall fail and return non-zero.]
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SetRetryPolicy_NULL_handle)
  {
      // arrange
      initialize_test_variables();
  
      umock_c_reset_all_calls();
  
      // act
      int result = IoTHubTransport_AMQP_Common_SetRetryPolicy(NULL, IOTHUB_CLIENT_RETRY_IMMEDIATE, 1600);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_130: [If retry_control_create() fails, `IoTHubTransport_AMQP_Common_SetRetryPolicy` shall fail and return non-zero.]
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SetRetryPolicy_failure_checks)
  {
      // arrange
      ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init());
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(retry_control_create(IOTHUB_CLIENT_RETRY_IMMEDIATE, 1600));
      umock_c_negative_tests_snapshot();
  
      // act
      size_t i;
      for (i = 0; i < umock_c_negative_tests_call_count(); i++)
      {
          // arrange
          char error_msg[64];
  
          umock_c_negative_tests_reset();
          umock_c_negative_tests_fail_call(i);
  
          // act
          int result = IoTHubTransport_AMQP_Common_SetRetryPolicy(handle, IOTHUB_CLIENT_RETRY_IMMEDIATE, 1600);
  
          // assert
          sprintf(error_msg, "On failed call %lu", (unsigned long)i);
          ASSERT_ARE_NOT_EQUAL(int, 0, result, error_msg);
      }
  
      // cleanup
      umock_c_negative_tests_deinit();
      destroy_transport(handle, NULL, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_129: [`transport_instance->connection_retry_control` shall be set using retry_control_create(), passing `retryPolicy` and `retryTimeoutLimitInSeconds`.]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_128: [If no errors occur, `IoTHubTransport_AMQP_Common_SetRetryPolicy` shall return zero.]
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_SetRetryPolicy_success)
  {
      // arrange
      initialize_test_variables();
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(retry_control_create(IOTHUB_CLIENT_RETRY_IMMEDIATE, 1600));
      STRICT_EXPECTED_CALL(retry_control_destroy(TEST_RETRY_CONTROL_HANDLE));
  
      // act
      int result = IoTHubTransport_AMQP_Common_SetRetryPolicy(handle, IOTHUB_CLIENT_RETRY_IMMEDIATE, 1600);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(int, 0, result);
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  TEST_FUNCTION(IoTHubTransport_AMQP_SetCallbackContext_success)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle = create_transport();
      umock_c_reset_all_calls();
  
      // act
      int result = IoTHubTransport_AMQP_SetCallbackContext(handle, transport_cb_ctx);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(int, 0, result);
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  TEST_FUNCTION(IoTHubTransport_AMQP_SetCallbackContext_fail)
  {
      // arrange
  
      // act
      int result = IoTHubTransport_AMQP_SetCallbackContext(NULL, transport_cb_ctx);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_155: [ amqp_device_get_twin_async() shall be invoked for the registered device, passing `on_device_get_twin_completed_callback`]
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_157: [ If no errors occur, `IoTHubTransport_AMQP_Common_GetTwinAsync` shall return IOTHUB_CLIENT_OK ]
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_GetTwinAsync_success)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE registered_devices[1];
      registered_devices[0] = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_NUM_ARG));
      STRICT_EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_NUM_ARG));
      STRICT_EXPECTED_CALL(malloc(IGNORED_NUM_ARG));
      STRICT_EXPECTED_CALL(amqp_device_get_twin_async(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG));
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_GetTwinAsync(handle, on_device_get_twin_completed_callback, (void*)0x5566);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result);
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_154: [ If `handle` or `completionCallback` are NULL, `IoTHubTransport_AMQP_Common_GetTwinAsync` shall fail and return IOTHUB_CLIENT_INVALID_ARG ]
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_GetTwinAsync_NULL_handle)
  {
      // arrange
      umock_c_reset_all_calls();
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_GetTwinAsync(NULL, on_device_get_twin_completed_callback, (void*)0x5566);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
  
      // cleanup
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_154: [ If `handle` or `completionCallback` are NULL, `IoTHubTransport_AMQP_Common_GetTwinAsync` shall fail and return IOTHUB_CLIENT_INVALID_ARG ]
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_GetTwinAsync_NULL_callback)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE registered_devices[1];
      registered_devices[0] = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
  
      // act
      IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_GetTwinAsync(handle, NULL, (void*)0x5566);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_INVALID_ARG, result);
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  // Tests_SRS_IOTHUBTRANSPORT_AMQP_COMMON_09_156: [ If amqp_device_get_twin_async() fails, `IoTHubTransport_AMQP_Common_GetTwinAsync` shall fail and return IOTHUB_CLIENT_ERROR ]
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_GetTwinAsync_failure_checks)
  {
      // arrange
      ASSERT_ARE_EQUAL(int, 0, umock_c_negative_tests_init());
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      IOTHUB_DEVICE_CONFIG* device_config = create_device_config(TEST_DEVICE_ID_CHAR_PTR, true);
  
      IOTHUB_DEVICE_HANDLE registered_devices[1];
      registered_devices[0] = register_device(handle, device_config, &TEST_waitingToSend, true);
  
      crank_transport_ready_after_create(handle, &TEST_waitingToSend, 0, false, true, 1, TEST_current_time, false);
  
      umock_c_reset_all_calls();
      STRICT_EXPECTED_CALL(singlylinkedlist_get_head_item(IGNORED_NUM_ARG))
          .CallCannotFail();
      STRICT_EXPECTED_CALL(singlylinkedlist_get_next_item(IGNORED_NUM_ARG))
          .CallCannotFail();
      STRICT_EXPECTED_CALL(malloc(IGNORED_NUM_ARG));
      STRICT_EXPECTED_CALL(amqp_device_get_twin_async(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG));
      umock_c_negative_tests_snapshot();
  
      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))
          {
              continue;
          }
  
          umock_c_negative_tests_reset();
          umock_c_negative_tests_fail_call(index);
  
          char tmp_msg[64];
          sprintf(tmp_msg, "Failure in test %lu/%lu", (unsigned long)index, (unsigned long)count);
          IOTHUB_CLIENT_RESULT result = IoTHubTransport_AMQP_Common_GetTwinAsync(handle, on_device_get_twin_completed_callback, (void*)0x5566);
  
          // assert
          ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_ERROR, result, tmp_msg);
      }
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
      umock_c_negative_tests_deinit();
  }
  
  
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_GetSupportedPlatformInfo_success)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      PLATFORM_INFO_OPTION info;
  
      umock_c_reset_all_calls();
  
      // act
      int result = IoTHubTransport_AMQP_Common_GetSupportedPlatformInfo(handle, &info);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_EQUAL(int, 0, result);
      ASSERT_ARE_EQUAL(int, info, PLATFORM_INFO_OPTION_RETRIEVE_SQM);
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_GetSupportedPlatformInfo_NULL_handle)
  {
      // arrange
      PLATFORM_INFO_OPTION info;
  
      umock_c_reset_all_calls();
  
      // act
      int result = IoTHubTransport_AMQP_Common_GetSupportedPlatformInfo(NULL, &info);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
  
      // cleanup
  }
  
  TEST_FUNCTION(IoTHubTransport_AMQP_Common_GetSupportedPlatformInfo_NULL_info)
  {
      // arrange
      TRANSPORT_LL_HANDLE handle = create_transport();
  
      umock_c_reset_all_calls();
  
      // act
      int result = IoTHubTransport_AMQP_Common_GetSupportedPlatformInfo(handle, NULL);
  
      // assert
      ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
      ASSERT_ARE_NOT_EQUAL(int, 0, result);
  
      // cleanup
      destroy_transport(handle, NULL, NULL);
  }
  
  END_TEST_SUITE(iothubtransport_amqp_common_ut)
  