diff --git a/.gitmodules b/.gitmodules index 1fd41083..1d4292c3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "c/azure-c-shared-utility"] path = c/azure-c-shared-utility url = https://github.com/Azure/azure-c-shared-utility.git +[submodule "c/azure-umqtt-c"] + path = c/azure-umqtt-c + url = https://github.com/Azure/azure-umqtt-c.git + branch = develop diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt index 38583712..d581aaec 100644 --- a/c/CMakeLists.txt +++ b/c/CMakeLists.txt @@ -25,6 +25,7 @@ if(IN_OPENWRT) endif() add_subdirectory(azure-c-shared-utility/c) +add_subdirectory(azure-umqtt-c) enable_testing() @@ -68,21 +69,14 @@ function(linkProton whatExecutableIsBuilding) endif() endfunction(linkProton) -function(includePaho) -#function body to be similar to includeProton -endfunction(includePaho) +function(includeMqtt) + include_directories(${MQTT_INC_FOLDER}) +endfunction(includeMqtt) -function(linkPaho whatExecutableIsBuilding) - includePaho() - if(WIN32) - target_link_libraries(${whatExecutableIsBuilding} "$ENV{paho_path}/org.eclipse.paho.mqtt.c/Windows Build/paho-mqtt3cs/Debug/paho-mqtt3cs.lib") - file(COPY "$ENV{paho_path}/org.eclipse.paho.mqtt.c/Windows Build/paho-mqtt3cs/Debug/paho-mqtt3cs.dll" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Debug) - file(COPY "$ENV{openssldir}/bin/libeay32.dll" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Debug) - file(COPY "$ENV{openssldir}/bin/ssleay32.dll" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Debug) - else() - target_link_libraries(${whatExecutableIsBuilding} paho-mqtt3cs) - endif() -endfunction(linkPaho) +function(linkMqttLibrary whatExecutableIsBuilding) + includeMqtt() + target_link_libraries(${whatExecutableIsBuilding} umqtt) +endfunction(linkMqttLibrary) function(includeHttp) #function body to be similar to includeProton @@ -240,7 +234,6 @@ function(build_test_artifacts whatIsBuilding use_gballoc) windows_unittests_add_exe(${whatIsBuilding} ${ARGN}) endif() endif() - endfunction(build_test_artifacts) set(SHARED_UTIL_ADAPTER_FOLDER "${CMAKE_CURRENT_LIST_DIR}/azure-c-shared-utility/c/adapters") diff --git a/c/azure-umqtt-c b/c/azure-umqtt-c new file mode 160000 index 00000000..8eee4032 --- /dev/null +++ b/c/azure-umqtt-c @@ -0,0 +1 @@ +Subproject commit 8eee4032b64ce3de322571f24559b33e0cf3e408 diff --git a/c/build_all/linux/build_paho.sh b/c/build_all/linux/build_paho.sh deleted file mode 100755 index 01b81d8e..00000000 --- a/c/build_all/linux/build_paho.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash - -set -e - -paho_repo="https://git.eclipse.org/r/paho/org.eclipse.paho.mqtt.c" -build_root= - -push_dir () -{ - pushd $1 > /dev/null - echo "In ${PWD#$build_root/}" -} - -pop_dir () -{ - popd > /dev/null -} - -usage () -{ - echo 'build_paho.sh [options]' - echo 'options' - echo ' -s, --source destination directory for paho source' - echo ' (default: $HOME/org.eclipse.paho.mqtt.c)' - echo ' -i, --install destination root directory for paho installation' - echo ' (default: $HOME)' - exit 1 -} - -process_args () -{ - build_root="$HOME/org.eclipse.paho.mqtt.c" - install_root="$HOME" - - while [ ! -z "$1" ] && [ ! -z "$2" ] - do - if [ "$1" == "-s" ] || [ "$1" == "--source" ] - then - build_root="$2" - elif [ "$1" == "-i" ] || [ "$1" == "--install" ] - then - install_root="$2" - else - usage - fi - - shift - shift - done - - if [ ! -z "$1" ] && [ -z "$2" ] - then #odd number of arguments - usage - fi -} - -sync_paho () -{ - echo Azure IoT SDK has a dependency on eclipse paho mqtt c sdk - echo http://www.eclipse.org/legal/CLA.php - - read -p "Do you want to install the component (y/n)?" input_var - if [ "$input_var" == "y" ] || [ "$input_var" == "Y" ] - then - echo "preparing qpid proton-c" - else - exit 1 - fi - - rm $build_root -r -f - mkdir $build_root - git clone $paho_repo $build_root -} - -build () -{ - push_dir $build_root - make install - pop_dir -} - -process_args $* -echo "Source: $build_root" -echo "Install: $install_root" -sync_paho -build diff --git a/c/build_all/linux/setup.sh b/c/build_all/linux/setup.sh index 2a28e0df..2f233362 100755 --- a/c/build_all/linux/setup.sh +++ b/c/build_all/linux/setup.sh @@ -51,20 +51,6 @@ install_proton_from_source () [ $? -eq 0 ] || return $? } -install_paho_from_source () -{ - #Skip if already installed - code_dir="$HOME/org.eclipse.paho.mqtt.c" - if [ -d $code_dir ] && [ -d "$code_dir/build/output" ] - then - echo "Paho already installed." - return 0 - fi - - sudo bash c/build_all/linux/build_paho.sh --install /usr - [ $? -eq 0 ] || return $? -} - deps_install if repo_exists @@ -77,5 +63,4 @@ else fi install_proton_from_source || exit 1 -install_paho_from_source || exit 1 pop_dir diff --git a/c/build_all/linux/setup_opensuse.sh b/c/build_all/linux/setup_opensuse.sh index f697b6f8..99b70cb8 100755 --- a/c/build_all/linux/setup_opensuse.sh +++ b/c/build_all/linux/setup_opensuse.sh @@ -85,18 +85,6 @@ install_proton_from_source () sudo bash c/build_all/linux/build_proton.sh --install /usr } -install_paho_from_source () -{ - #Skip if already installed - code_dir="$HOME/org.eclipse.paho.mqtt.c" - if [ -d $code_dir ] && [ -d "$code_dir/build/output" ] - then - echo "Paho already installed." - return 0 - fi - - sudo bash c/build_all/linux/build_paho.sh --install /usr -} if ! repo_exists then @@ -117,5 +105,4 @@ else fi install_proton_from_source -install_paho_from_source pop_dir diff --git a/c/build_all/packaging/windows/Eclipse.Paho-C.paho-mqtt3cs.nuspec b/c/build_all/packaging/windows/Eclipse.Paho-C.paho-mqtt3cs.nuspec deleted file mode 100644 index d8d9dc4b..00000000 --- a/c/build_all/packaging/windows/Eclipse.Paho-C.paho-mqtt3cs.nuspec +++ /dev/null @@ -1,51 +0,0 @@ - - - Eclipse.Paho-C.paho-mqtt3cs - 1.0.3 - Eclipse Paho-C mqtt3cs Library - Eclipse Org, Microsoft Corp - Azure-IoT - https://github.com/eclipse/paho.mqtt.c/blob/master/notice.html - https://www.eclipse.org/paho/clients/c/ - true - This package brings the Paho MQTT C Client, which is a fully fledged MQTT client written in ANSI standard C. - http://go.microsoft.com/fwlink/?LinkID=288890 - - The Paho MQTT C Client library provides 2 set of APIs: "Synchronous" and "Asynchronous" Ones. - The API calls will start with MQTTClient for Synchronous APIs, and MQTT Async for Asynchronous ones. - This package only contains the Synchronous mqtt3cs with Security (Using Open SSL). - Microsoft's contribution to this package was only the packaging for NuGet itself. The library has been developed and is maintained by the Eclipse Foundation. - - - Copyright 2015 - MQTT Paho Eclipse Native x86 x64 package - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/c/build_all/packaging/windows/Eclipse.Paho-C.paho-mqtt3cs.targets b/c/build_all/packaging/windows/Eclipse.Paho-C.paho-mqtt3cs.targets deleted file mode 100644 index a8926952..00000000 --- a/c/build_all/packaging/windows/Eclipse.Paho-C.paho-mqtt3cs.targets +++ /dev/null @@ -1,91 +0,0 @@ - - - - static - cdecl - - - - $(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories) - WIN32;%(PreprocessorDefinitions) - - - $(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories) - - - - - $(MSBuildThisFileDirectory)../../lib/native/Win32/Debug/paho-mqtt3cs.lib;%(AdditionalDependencies) - - - - - $(MSBuildThisFileDirectory)../../lib/native/Win32/Release/paho-mqtt3cs.lib;%(AdditionalDependencies) - - - - - $(MSBuildThisFileDirectory)../../lib/native/x64/Debug/paho-mqtt3cs.lib;%(AdditionalDependencies) - - - - - $(MSBuildThisFileDirectory)../../lib/native/x64/Release/paho-mqtt3cs.lib;%(AdditionalDependencies) - - - - - - - - - - - Result = ((Text ?? "").Split(';').Contains(Library) ) ? Value : String.Empty; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/c/build_all/packaging/windows/Eclipse.Paho-C.paho-mqtt3cs_thirdpartynotice.txt b/c/build_all/packaging/windows/Eclipse.Paho-C.paho-mqtt3cs_thirdpartynotice.txt deleted file mode 100644 index d6941463..00000000 --- a/c/build_all/packaging/windows/Eclipse.Paho-C.paho-mqtt3cs_thirdpartynotice.txt +++ /dev/null @@ -1,245 +0,0 @@ -Third Party Notices for Azure IoT SDKs project - -This project incorporates material from the project(s) listed below (collectively, “Third Party Code”). -Microsoft Corporation is not the original author of the Third Party Code. -The original copyright notice and license, under which Microsoft Corporation received such Third Party Code, -are set out below. This Third Party Code is licensed to you under their original license terms set forth below. -Microsoft Corporation reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. - -1. Paho C v1.0.3, obtained from https://www.eclipse.org/paho/clients/c/ - -/* -Eclipse Public License - v 1.0 - -THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE - PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR - DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS - AGREEMENT. - -1. DEFINITIONS - -"Contribution" means: - -a) in the case of the initial Contributor, the initial - code and documentation distributed under this Agreement, and - -b) in the case of each subsequent Contributor: - -i) changes to the Program, and - -ii) additions to the Program; - -where such changes and/or additions to the Program - originate from and are distributed by that particular Contributor. A - Contribution 'originates' from a Contributor if it was added to the - Program by such Contributor itself or anyone acting on such - Contributor's behalf. Contributions do not include additions to the - Program which: (i) are separate modules of software distributed in - conjunction with the Program under their own license agreement, and (ii) - are not derivative works of the Program. - -"Contributor" means any person or entity that distributes - the Program. - -"Licensed Patents" mean patent claims licensable by a - Contributor which are necessarily infringed by the use or sale of its - Contribution alone or when combined with the Program. - -"Program" means the Contributions distributed in accordance - with this Agreement. - -"Recipient" means anyone who receives the Program under - this Agreement, including all Contributors. - -2. GRANT OF RIGHTS - -a) Subject to the terms of this Agreement, each - Contributor hereby grants Recipient a non-exclusive, worldwide, - royalty-free copyright license to reproduce, prepare derivative works - of, publicly display, publicly perform, distribute and sublicense the - Contribution of such Contributor, if any, and such derivative works, in - source code and object code form. - -b) Subject to the terms of this Agreement, each - Contributor hereby grants Recipient a non-exclusive, worldwide, - royalty-free patent license under Licensed Patents to make, use, sell, - offer to sell, import and otherwise transfer the Contribution of such - Contributor, if any, in source code and object code form. This patent - license shall apply to the combination of the Contribution and the - Program if, at the time the Contribution is added by the Contributor, - such addition of the Contribution causes such combination to be covered - by the Licensed Patents. The patent license shall not apply to any other - combinations which include the Contribution. No hardware per se is - licensed hereunder. - -c) Recipient understands that although each Contributor - grants the licenses to its Contributions set forth herein, no assurances - are provided by any Contributor that the Program does not infringe the - patent or other intellectual property rights of any other entity. Each - Contributor disclaims any liability to Recipient for claims brought by - any other entity based on infringement of intellectual property rights - or otherwise. As a condition to exercising the rights and licenses - granted hereunder, each Recipient hereby assumes sole responsibility to - secure any other intellectual property rights needed, if any. For - example, if a third party patent license is required to allow Recipient - to distribute the Program, it is Recipient's responsibility to acquire - that license before distributing the Program. - -d) Each Contributor represents that to its knowledge it - has sufficient copyright rights in its Contribution, if any, to grant - the copyright license set forth in this Agreement. - -3. REQUIREMENTS - -A Contributor may choose to distribute the Program in object code - form under its own license agreement, provided that: - -a) it complies with the terms and conditions of this - Agreement; and - -b) its license agreement: - -i) effectively disclaims on behalf of all Contributors - all warranties and conditions, express and implied, including warranties - or conditions of title and non-infringement, and implied warranties or - conditions of merchantability and fitness for a particular purpose; - -ii) effectively excludes on behalf of all Contributors - all liability for damages, including direct, indirect, special, - incidental and consequential damages, such as lost profits; - -iii) states that any provisions which differ from this - Agreement are offered by that Contributor alone and not by any other - party; and - -iv) states that source code for the Program is available - from such Contributor, and informs licensees how to obtain it in a - reasonable manner on or through a medium customarily used for software - exchange. - -When the Program is made available in source code form: - -a) it must be made available under this Agreement; and - -b) a copy of this Agreement must be included with each - copy of the Program. - -Contributors may not remove or alter any copyright notices contained - within the Program. - -Each Contributor must identify itself as the originator of its - Contribution, if any, in a manner that reasonably allows subsequent - Recipients to identify the originator of the Contribution. - -4. COMMERCIAL DISTRIBUTION - -Commercial distributors of software may accept certain - responsibilities with respect to end users, business partners and the - like. While this license is intended to facilitate the commercial use of - the Program, the Contributor who includes the Program in a commercial - product offering should do so in a manner which does not create - potential liability for other Contributors. Therefore, if a Contributor - includes the Program in a commercial product offering, such Contributor - ("Commercial Contributor") hereby agrees to defend and - indemnify every other Contributor ("Indemnified Contributor") - against any losses, damages and costs (collectively "Losses") - arising from claims, lawsuits and other legal actions brought by a third - party against the Indemnified Contributor to the extent caused by the - acts or omissions of such Commercial Contributor in connection with its - distribution of the Program in a commercial product offering. The - obligations in this section do not apply to any claims or Losses - relating to any actual or alleged intellectual property infringement. In - order to qualify, an Indemnified Contributor must: a) promptly notify - the Commercial Contributor in writing of such claim, and b) allow the - Commercial Contributor to control, and cooperate with the Commercial - Contributor in, the defense and any related settlement negotiations. The - Indemnified Contributor may participate in any such claim at its own - expense. - -For example, a Contributor might include the Program in a commercial - product offering, Product X. That Contributor is then a Commercial - Contributor. If that Commercial Contributor then makes performance - claims, or offers warranties related to Product X, those performance - claims and warranties are such Commercial Contributor's responsibility - alone. Under this section, the Commercial Contributor would have to - defend claims against the other Contributors related to those - performance claims and warranties, and if a court requires any other - Contributor to pay any damages as a result, the Commercial Contributor - must pay those damages. - -5. NO WARRANTY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS - PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS - OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, - ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY - OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely - responsible for determining the appropriateness of using and - distributing the Program and assumes all risks associated with its - exercise of rights under this Agreement , including but not limited to - the risks and costs of program errors, compliance with applicable laws, - damage to or loss of data, programs or equipment, and unavailability or - interruption of operations. - -6. DISCLAIMER OF LIABILITY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT - NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING - WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR - DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -7. GENERAL - -If any provision of this Agreement is invalid or unenforceable under - applicable law, it shall not affect the validity or enforceability of - the remainder of the terms of this Agreement, and without further action - by the parties hereto, such provision shall be reformed to the minimum - extent necessary to make such provision valid and enforceable. - -If Recipient institutes patent litigation against any entity - (including a cross-claim or counterclaim in a lawsuit) alleging that the - Program itself (excluding combinations of the Program with other - software or hardware) infringes such Recipient's patent(s), then such - Recipient's rights granted under Section 2(b) shall terminate as of the - date such litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it - fails to comply with any of the material terms or conditions of this - Agreement and does not cure such failure in a reasonable period of time - after becoming aware of such noncompliance. If all Recipient's rights - under this Agreement terminate, Recipient agrees to cease use and - distribution of the Program as soon as reasonably practicable. However, - Recipient's obligations under this Agreement and any licenses granted by - Recipient relating to the Program shall continue and survive. - -Everyone is permitted to copy and distribute copies of this - Agreement, but in order to avoid inconsistency the Agreement is - copyrighted and may only be modified in the following manner. The - Agreement Steward reserves the right to publish new versions (including - revisions) of this Agreement from time to time. No one other than the - Agreement Steward has the right to modify this Agreement. The Eclipse - Foundation is the initial Agreement Steward. The Eclipse Foundation may - assign the responsibility to serve as the Agreement Steward to a - suitable separate entity. Each new version of the Agreement will be - given a distinguishing version number. The Program (including - Contributions) may always be distributed subject to the version of the - Agreement under which it was received. In addition, after a new version - of the Agreement is published, Contributor may elect to distribute the - Program (including its Contributions) under the new version. Except as - expressly stated in Sections 2(a) and 2(b) above, Recipient receives no - rights or licenses to the intellectual property of any Contributor under - this Agreement, whether expressly, by implication, estoppel or - otherwise. All rights in the Program not expressly granted under this - Agreement are reserved. - -This Agreement is governed by the laws of the State of New York and - the intellectual property laws of the United States of America. No party - to this Agreement will bring a legal action under this Agreement more - than one year after the cause of action arose. Each party waives its - rights to a jury trial in any resulting litigation. - -*/ \ No newline at end of file diff --git a/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport.nuspec b/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport.nuspec index 99b5aaa8..11255396 100644 --- a/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport.nuspec +++ b/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport.nuspec @@ -15,21 +15,15 @@ Copyright 2015 MQTT Microsoft Azure IoT Native x86 native package - + - - + - - - - - diff --git a/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport.targets b/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport.targets index 7046f917..c7cff76f 100644 --- a/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport.targets +++ b/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport.targets @@ -14,7 +14,7 @@ - $(MSBuildThisFileDirectory)../../build/native/Win32/Debug/paho-mqtt3cs.lib;$(MSBuildThisFileDirectory)../../build/native/Win32/Debug/iothub_client_mqtt_transport.lib;%(AdditionalDependencies) + $(MSBuildThisFileDirectory)../../build/native/Win32/Debug/iothub_client_mqtt_transport.lib;%(AdditionalDependencies) @@ -57,14 +57,7 @@ - + - - - - - - - - + \ No newline at end of file diff --git a/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport_thirdpartynotice.txt b/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport_thirdpartynotice.txt index b42c4997..0a6267e6 100644 --- a/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport_thirdpartynotice.txt +++ b/c/build_all/packaging/windows/Microsoft.Azure.IoTHub.MqttTransport_thirdpartynotice.txt @@ -6,369 +6,3 @@ The original copyright notice and license, under which Microsoft Corporation rec are set out below. This Third Party Code is licensed to you under their original license terms set forth below. Microsoft Corporation reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. -1. Paho C v1.0.3, obtained from https://www.eclipse.org/paho/clients/c/ - -/* -Eclipse Public License - v 1.0 - -THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE - PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR - DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS - AGREEMENT. - -1. DEFINITIONS - -"Contribution" means: - -a) in the case of the initial Contributor, the initial - code and documentation distributed under this Agreement, and - -b) in the case of each subsequent Contributor: - -i) changes to the Program, and - -ii) additions to the Program; - -where such changes and/or additions to the Program - originate from and are distributed by that particular Contributor. A - Contribution 'originates' from a Contributor if it was added to the - Program by such Contributor itself or anyone acting on such - Contributor's behalf. Contributions do not include additions to the - Program which: (i) are separate modules of software distributed in - conjunction with the Program under their own license agreement, and (ii) - are not derivative works of the Program. - -"Contributor" means any person or entity that distributes - the Program. - -"Licensed Patents" mean patent claims licensable by a - Contributor which are necessarily infringed by the use or sale of its - Contribution alone or when combined with the Program. - -"Program" means the Contributions distributed in accordance - with this Agreement. - -"Recipient" means anyone who receives the Program under - this Agreement, including all Contributors. - -2. GRANT OF RIGHTS - -a) Subject to the terms of this Agreement, each - Contributor hereby grants Recipient a non-exclusive, worldwide, - royalty-free copyright license to reproduce, prepare derivative works - of, publicly display, publicly perform, distribute and sublicense the - Contribution of such Contributor, if any, and such derivative works, in - source code and object code form. - -b) Subject to the terms of this Agreement, each - Contributor hereby grants Recipient a non-exclusive, worldwide, - royalty-free patent license under Licensed Patents to make, use, sell, - offer to sell, import and otherwise transfer the Contribution of such - Contributor, if any, in source code and object code form. This patent - license shall apply to the combination of the Contribution and the - Program if, at the time the Contribution is added by the Contributor, - such addition of the Contribution causes such combination to be covered - by the Licensed Patents. The patent license shall not apply to any other - combinations which include the Contribution. No hardware per se is - licensed hereunder. - -c) Recipient understands that although each Contributor - grants the licenses to its Contributions set forth herein, no assurances - are provided by any Contributor that the Program does not infringe the - patent or other intellectual property rights of any other entity. Each - Contributor disclaims any liability to Recipient for claims brought by - any other entity based on infringement of intellectual property rights - or otherwise. As a condition to exercising the rights and licenses - granted hereunder, each Recipient hereby assumes sole responsibility to - secure any other intellectual property rights needed, if any. For - example, if a third party patent license is required to allow Recipient - to distribute the Program, it is Recipient's responsibility to acquire - that license before distributing the Program. - -d) Each Contributor represents that to its knowledge it - has sufficient copyright rights in its Contribution, if any, to grant - the copyright license set forth in this Agreement. - -3. REQUIREMENTS - -A Contributor may choose to distribute the Program in object code - form under its own license agreement, provided that: - -a) it complies with the terms and conditions of this - Agreement; and - -b) its license agreement: - -i) effectively disclaims on behalf of all Contributors - all warranties and conditions, express and implied, including warranties - or conditions of title and non-infringement, and implied warranties or - conditions of merchantability and fitness for a particular purpose; - -ii) effectively excludes on behalf of all Contributors - all liability for damages, including direct, indirect, special, - incidental and consequential damages, such as lost profits; - -iii) states that any provisions which differ from this - Agreement are offered by that Contributor alone and not by any other - party; and - -iv) states that source code for the Program is available - from such Contributor, and informs licensees how to obtain it in a - reasonable manner on or through a medium customarily used for software - exchange. - -When the Program is made available in source code form: - -a) it must be made available under this Agreement; and - -b) a copy of this Agreement must be included with each - copy of the Program. - -Contributors may not remove or alter any copyright notices contained - within the Program. - -Each Contributor must identify itself as the originator of its - Contribution, if any, in a manner that reasonably allows subsequent - Recipients to identify the originator of the Contribution. - -4. COMMERCIAL DISTRIBUTION - -Commercial distributors of software may accept certain - responsibilities with respect to end users, business partners and the - like. While this license is intended to facilitate the commercial use of - the Program, the Contributor who includes the Program in a commercial - product offering should do so in a manner which does not create - potential liability for other Contributors. Therefore, if a Contributor - includes the Program in a commercial product offering, such Contributor - ("Commercial Contributor") hereby agrees to defend and - indemnify every other Contributor ("Indemnified Contributor") - against any losses, damages and costs (collectively "Losses") - arising from claims, lawsuits and other legal actions brought by a third - party against the Indemnified Contributor to the extent caused by the - acts or omissions of such Commercial Contributor in connection with its - distribution of the Program in a commercial product offering. The - obligations in this section do not apply to any claims or Losses - relating to any actual or alleged intellectual property infringement. In - order to qualify, an Indemnified Contributor must: a) promptly notify - the Commercial Contributor in writing of such claim, and b) allow the - Commercial Contributor to control, and cooperate with the Commercial - Contributor in, the defense and any related settlement negotiations. The - Indemnified Contributor may participate in any such claim at its own - expense. - -For example, a Contributor might include the Program in a commercial - product offering, Product X. That Contributor is then a Commercial - Contributor. If that Commercial Contributor then makes performance - claims, or offers warranties related to Product X, those performance - claims and warranties are such Commercial Contributor's responsibility - alone. Under this section, the Commercial Contributor would have to - defend claims against the other Contributors related to those - performance claims and warranties, and if a court requires any other - Contributor to pay any damages as a result, the Commercial Contributor - must pay those damages. - -5. NO WARRANTY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS - PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS - OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, - ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY - OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely - responsible for determining the appropriateness of using and - distributing the Program and assumes all risks associated with its - exercise of rights under this Agreement , including but not limited to - the risks and costs of program errors, compliance with applicable laws, - damage to or loss of data, programs or equipment, and unavailability or - interruption of operations. - -6. DISCLAIMER OF LIABILITY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT - NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING - WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR - DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -7. GENERAL - -If any provision of this Agreement is invalid or unenforceable under - applicable law, it shall not affect the validity or enforceability of - the remainder of the terms of this Agreement, and without further action - by the parties hereto, such provision shall be reformed to the minimum - extent necessary to make such provision valid and enforceable. - -If Recipient institutes patent litigation against any entity - (including a cross-claim or counterclaim in a lawsuit) alleging that the - Program itself (excluding combinations of the Program with other - software or hardware) infringes such Recipient's patent(s), then such - Recipient's rights granted under Section 2(b) shall terminate as of the - date such litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it - fails to comply with any of the material terms or conditions of this - Agreement and does not cure such failure in a reasonable period of time - after becoming aware of such noncompliance. If all Recipient's rights - under this Agreement terminate, Recipient agrees to cease use and - distribution of the Program as soon as reasonably practicable. However, - Recipient's obligations under this Agreement and any licenses granted by - Recipient relating to the Program shall continue and survive. - -Everyone is permitted to copy and distribute copies of this - Agreement, but in order to avoid inconsistency the Agreement is - copyrighted and may only be modified in the following manner. The - Agreement Steward reserves the right to publish new versions (including - revisions) of this Agreement from time to time. No one other than the - Agreement Steward has the right to modify this Agreement. The Eclipse - Foundation is the initial Agreement Steward. The Eclipse Foundation may - assign the responsibility to serve as the Agreement Steward to a - suitable separate entity. Each new version of the Agreement will be - given a distinguishing version number. The Program (including - Contributions) may always be distributed subject to the version of the - Agreement under which it was received. In addition, after a new version - of the Agreement is published, Contributor may elect to distribute the - Program (including its Contributions) under the new version. Except as - expressly stated in Sections 2(a) and 2(b) above, Recipient receives no - rights or licenses to the intellectual property of any Contributor under - this Agreement, whether expressly, by implication, estoppel or - otherwise. All rights in the Program not expressly granted under this - Agreement are reserved. - -This Agreement is governed by the laws of the State of New York and - the intellectual property laws of the United States of America. No party - to this Agreement will bring a legal action under this Agreement more - than one year after the cause of action arose. Each party waives its - rights to a jury trial in any resulting litigation. - -*/ - -2. OpenSSL, obtained from https://github.com/openssl/openssl.git - - LICENSE ISSUES - ============== - - The OpenSSL toolkit stays under a dual license, i.e. both the conditions of - the OpenSSL License and the original SSLeay license apply to the toolkit. - See below for the actual license texts. Actually both licenses are BSD-style - Open Source licenses. In case of any license issues related to OpenSSL - please contact openssl-core@openssl.org. - - OpenSSL License - --------------- - -/* ==================================================================== - * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - - Original SSLeay License - ----------------------- - -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - diff --git a/c/build_all/packaging/windows/rebuild_nugets.cmd b/c/build_all/packaging/windows/rebuild_nugets.cmd index 5fe80e66..03594113 100644 --- a/c/build_all/packaging/windows/rebuild_nugets.cmd +++ b/c/build_all/packaging/windows/rebuild_nugets.cmd @@ -61,80 +61,8 @@ nuget pack Microsoft.Azure.IoTHub.HttpTransport.nuspec nuget pack Microsoft.Azure.IoTHub.AmqpTransport.nuspec nuget pack Microsoft.Azure.IoTHub.IoTHubClient.nuspec -rem because nuget cannot access absolute files given by environment variables -mkdir paho_outputs -cd paho_outputs -mkdir Win32 -mkdir x64 -mkdir include -cd Win32 -mkdir Release -mkdir Debug -cd .. -cd x64 -mkdir Release -mkdir Debug -cd .. -cd .. - -rem -- Copy Win32 Paho Files. -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\Debug\paho-mqtt3cs.lib" paho_outputs\Win32\Debug -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\Debug\paho-mqtt3cs.pdb" paho_outputs\Win32\Debug -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\Debug\paho-mqtt3cs.dll" paho_outputs\Win32\Debug - -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\Windows Build\build\output\paho-mqtt3cs.lib" paho_outputs\Win32\Release -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\Windows Build\build\output\paho-mqtt3cs.dll" paho_outputs\Win32\Release - -rem -- Copy 64 bits Paho Files. -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\x64\Debug\paho-mqtt3cs.lib" paho_outputs\x64\Debug -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\x64\Debug\paho-mqtt3cs.pdb" paho_outputs\x64\Debug -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\x64\Debug\paho-mqtt3cs.dll" paho_outputs\x64\Debug - -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\x64\Release\paho-mqtt3cs.lib" paho_outputs\x64\Release -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\x64\Release\paho-mqtt3cs.dll" paho_outputs\x64\Release - -rem -- Copy Header Files -copy "%PAHO_PATH%\org.eclipse.paho.mqtt.c\src\*.h" paho_outputs\include - - -mkdir openssl_outputs -cd openssl_outputs -mkdir Win32 -cd Win32 -mkdir Debug -cd .. -mkdir x64 -cd x64 -mkdir Debug -cd .. -cd .. - -copy "%OpenSSLDir%\out32dllForNuget\libeay32.dll" openssl_outputs\Win32\Debug -copy "%OpenSSLDir%\out32dllForNuget\libeay32.lib" openssl_outputs\Win32\Debug -copy "%OpenSSLDir%\out32dllForNuget\libeay32.exp" openssl_outputs\Win32\Debug -copy "%OpenSSLDir%\out32dllForNuget\libeay32.pdb" openssl_outputs\Win32\Debug -copy "%OpenSSLDir%\out32dllForNuget\ssleay32.dll" openssl_outputs\Win32\Debug -copy "%OpenSSLDir%\out32dllForNuget\ssleay32.lib" openssl_outputs\Win32\Debug -copy "%OpenSSLDir%\out32dllForNuget\ssleay32.exp" openssl_outputs\Win32\Debug -copy "%OpenSSLDir%\out32dllForNuget\ssleay32.pdb" openssl_outputs\Win32\Debug - -copy "%OpenSSLDir%\out64dll\libeay32.dll" openssl_outputs\x64\Debug -copy "%OpenSSLDir%\out64dll\libeay32.lib" openssl_outputs\x64\Debug -copy "%OpenSSLDir%\out64dll\libeay32.exp" openssl_outputs\x64\Debug -copy "%OpenSSLDir%\out64dll\libeay32.pdb" openssl_outputs\x64\Debug -copy "%OpenSSLDir%\out64dll\ssleay32.dll" openssl_outputs\x64\Debug -copy "%OpenSSLDir%\out64dll\ssleay32.lib" openssl_outputs\x64\Debug -copy "%OpenSSLDir%\out64dll\ssleay32.exp" openssl_outputs\x64\Debug -copy "%OpenSSLDir%\out64dll\ssleay32.pdb" openssl_outputs\x64\Debug - -nuget pack Eclipse.Paho-C.paho-mqtt3cs.nuspec - - nuget pack Microsoft.Azure.IoTHub.MqttTransport.nuspec -rmdir paho_outputs /S /Q -rmdir openssl_outputs /S /Q - nuget pack Microsoft.Azure.IoTHub.Serializer.nuspec rmdir %client-root%\build_output /S /Q diff --git a/c/build_all/windows/build_paho.cmd b/c/build_all/windows/build_paho.cmd deleted file mode 100644 index d4f81954..00000000 --- a/c/build_all/windows/build_paho.cmd +++ /dev/null @@ -1,172 +0,0 @@ -@setlocal EnableExtensions EnableDelayedExpansion -@echo off - -if not defined PAHO_PATH goto :errorPAHOPATHnotDefined -if not defined OpenSSLDir goto :errorOPenSSLDirnotDefined - -goto :continueWithInstallation - - -:errorPAHOPATHnotDefined -@Echo PAHO_PATH not defined. Please, Define PAHO_PATH on Environment Variables, restart command prompt and the script. -goto :eof - -:errorOPenSSLDirnotDefined -@Echo OpenSSLDir not defined. Please, Define OpenSSLDir on Environment Variables and restart the script. -goto :eof - -:continueWithInstallation - -rem ----------------------------------------------------------------------------- -rem -- use OpenSSLDir -rem ----------------------------------------------------------------------------- -set openSSL-root=%OpenSSLDir% -set openSSL-repo=https://github.com/openssl/openssl.git -set openSSL-build-root=%openSSL-root% -set openSSL-branch=OpenSSL_1_0_1-stable - -rem ----------------------------------------------------------------------------- -rem -- use PAHO_PATH -rem ----------------------------------------------------------------------------- -set paho-root=%PAHO_PATH% -set paho-repo=https://git.eclipse.org/r/paho/org.eclipse.paho.mqtt.c.git -rem -- Move this to master as soon as the x64 bit configuration is on master. -set paho-branch=develop -set package-root=%~dp0\..\packaging\windows -set paho-build-root=%paho-root%\org.eclipse.paho.mqtt.c - - -rem ----------------------------------------------------------------------------- -rem -- Make sure they know this is a third party component -rem ----------------------------------------------------------------------------- - -echo OpenSSL will be located at %openSSL-root% -echo. -echo Paho will be located at %paho-root% -echo. - -@Echo Azure IoT SDK has a dependency on OpenSSL and Paho MQTT -@Echo https://github.com/openssl/openssl/blob/OpenSSL_1_0_1-stable/LICENSE -@Echo http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt.c.git/tree/notice.html -choice /C yn /M "Do you want to install these components?" -if not %errorlevel%==1 goto :eof - -rem ----------------------------------------------------------------------------- -rem -Check Perl Version -@Echo This is your version of Perl. We require version 5.20 or higher. -perl -v -perl -v | findstr /i "(v5\.2*" > nul -IF %ERRORLEVEL% EQU 1 goto :wrongPerlVersion -goto :continueInstallingOpenSSL -:wrongPerlVersion -@Echo Seems like you have a wrong Perl Version. -@Echo Check your perl installation and make sure you install version 5.20 or higher and restart the script. -@Echo If you have multiple perl versions, make sure you set a supported one first on the PATH environment variable. -goto :eof -rem ----------------------------------------------------------------------------- - -rem ----------------------------------------------------------------------------- -rem -- sync the OpenSSL source code -rem ----------------------------------------------------------------------------- -:continueInstallingOpenSSL -if Exist %openSSL-root% rmdir %openSSL-root% /s /q -git clone -b %openSSL-branch% %openSSL-repo% %openSSL-build-root% -if not %errorlevel%==0 exit /b %errorlevel% - -rem ----------------------------------------------------------------------------- -rem -- build OpenSSL 32 bits -rem ----------------------------------------------------------------------------- - -call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86 -if not %errorlevel%==0 exit /b %errorlevel% - -pushd %openSSL-build-root% -perl Configure VC-WIN32 no-asm --prefix=%openSSL-build-root% -if not %errorlevel%==0 exit /b %errorlevel% - -call ms\do_ms.bat -if not %errorlevel%==0 exit /b %errorlevel% - -call nmake -f ms\ntdll.mak -if not %errorlevel%==0 exit /b %errorlevel% - -call nmake -f ms\ntdll.mak install -if not %errorlevel%==0 exit /b %errorlevel% - -mkdir out32dllForNuget -xcopy /q /y /R .\out32dll\*.* .\out32dllForNuget\*.* -if %errorlevel% neq 0 exit /b %errorlevel% - -rem ----------------------------------------------------------------------------- -rem -- sync the paho source code -rem ----------------------------------------------------------------------------- - -if Exist %paho-root% rmdir %paho-root% /s /q -git clone -b %paho-branch% %paho-repo% %paho-build-root% -if not %errorlevel%==0 exit /b %errorlevel% - -rem ----------------------------------------------------------------------------- -rem -- build paho 32 bits. -rem ----------------------------------------------------------------------------- - -pushd %paho-build-root% -if exist "%programfiles(x86)%\MSBuild\14.0\\." ( -msbuild ".\Windows Build\paho-mqtt3cs\paho-mqtt3cs.vcxproj" /p:Configuration=Debug;PlatformToolset=v140 -msbuild ".\Windows Build\paho-mqtt3cs\paho-mqtt3cs.vcxproj" /p:Configuration=Release;PlatformToolset=v140 -goto paho_build_done -) -if exist "%programfiles(x86)%\MSBuild\12.0\\." ( -msbuild ".\Windows Build\paho-mqtt3cs\paho-mqtt3cs.vcxproj" /p:Configuration=Debug -msbuild ".\Windows Build\paho-mqtt3cs\paho-mqtt3cs.vcxproj" /p:Configuration=Release -goto paho_build_done -) - -@Echo Paho MQTT needs Visual Studio 2013 or higher in order to build. -exit /b 1 -:paho_build_done -if not %errorlevel%==0 exit /b %errorlevel% - -rem ----------------------------------------------------------------------------- -rem -- build OpenSSL 64 bits -rem ----------------------------------------------------------------------------- - -call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 -if not %errorlevel%==0 exit /b %errorlevel% - -pushd %openSSL-build-root% -perl Configure VC-WIN64A -if not %errorlevel%==0 exit /b %errorlevel% - -call ms\do_win64a -if not %errorlevel%==0 exit /b %errorlevel% - -call nmake -f ms\ntdll.mak clean -if not %errorlevel%==0 exit /b %errorlevel% - -call nmake -f ms\ntdll.mak -if not %errorlevel%==0 exit /b %errorlevel% - -mkdir out64dll -xcopy /q /y /R .\out32dll\*.* .\out64dll\*.* -if %errorlevel% neq 0 exit /b %errorlevel% - -rem ----------------------------------------------------------------------------- -rem -- build paho 64 bits. -rem ----------------------------------------------------------------------------- - -pushd %paho-build-root% -if exist "%programfiles(x86)%\MSBuild\14.0\\." ( -msbuild ".\Windows Build\paho-mqtt3cs\paho-mqtt3cs.vcxproj" /p:Configuration=Debug;PlatformToolset=v140;Platform=x64 -msbuild ".\Windows Build\paho-mqtt3cs\paho-mqtt3cs.vcxproj" /p:Configuration=Release;PlatformToolset=v140;Platform=x64 -goto paho_build_done -) -if exist "%programfiles(x86)%\MSBuild\12.0\\." ( -msbuild ".\Windows Build\paho-mqtt3cs\paho-mqtt3cs.vcxproj" /p:Configuration=Debug;Platform=x64 -msbuild ".\Windows Build\paho-mqtt3cs\paho-mqtt3cs.vcxproj" /p:Configuration=Release;Platform=x64 -goto paho_build_done -) - -@Echo Paho MQTT needs Visual Studio 2013 or higher in order to build. -exit /b 1 -:paho_build_done -if not %errorlevel%==0 exit /b %errorlevel% \ No newline at end of file diff --git a/c/doc/devbox_setup.md b/c/doc/devbox_setup.md index b050c0f0..e2aeb5ac 100644 --- a/c/doc/devbox_setup.md +++ b/c/doc/devbox_setup.md @@ -64,9 +64,9 @@ You do *not* need to build the libraries in order to run the sample applications The following instructions outline how you can build the libraries in Windows: -1. Create the folders **C:\\Proton**, **C:\\OpenSSL**, and **C:\\Paho** on your development machine in which to download the dependencies. +1. Create the folders **C:\\Proton** and **C:\\OpenSSL** on your development machine in which to download the dependencies. -2. Create the environment variables **PROTON\_PATH=C:\\Proton**, **OpenSSLDir=C:\\OpenSSL**, and **PAHO\_PATH=C:\\Paho**.. +2. Create the environment variables **PROTON\_PATH=C:\\Proton** and **OpenSSLDir=C:\\OpenSSL**.. 3. Install [cmake](http://www.cmake.org/) (make sure it is installed in your path, type "cmake -version" to verify). @@ -80,9 +80,7 @@ The following instructions outline how you can build the libraries in Windows: 7. Run the script **build\_proton.cmd** in the **c\\build_all\\windows** directory to build the proton libraries. -8. Run the script **build\_paho.cmd** in the **c\\build_all\\windows** directory. - -9. Run the script **build\_client.cmd** in the **c\\build_all\\windows** directory. +8. Run the script **build\_client.cmd** in the **c\\build_all\\windows** directory. > Note: In order to test MQTT End2End you must also deploy an [Azure IoT Protocol Gateway](https://github.com/Azure/azure-iot-protocol-gateway/blob/master/README.md). diff --git a/c/doc/run_sample_on_ankaa_ubuntu12_04.md b/c/doc/run_sample_on_ankaa_ubuntu12_04.md index 751335dd..7aa098de 100644 --- a/c/doc/run_sample_on_ankaa_ubuntu12_04.md +++ b/c/doc/run_sample_on_ankaa_ubuntu12_04.md @@ -101,11 +101,7 @@ you obtained in the "Connecting your device to an IoT hub" step above. ``` sudo ./c/build_all/linux/build_proton.sh --install /usr ``` -- Build a few libraries upon which the samples depend: - ``` - sudo ~/azure-iot-sdks/c/build_all/linux/build_paho.sh - ``` - Finally, build the sample applications: ``` diff --git a/c/doc/run_sample_on_beaglebone_black_debian.md b/c/doc/run_sample_on_beaglebone_black_debian.md index d5213f1a..8a628f26 100644 --- a/c/doc/run_sample_on_beaglebone_black_debian.md +++ b/c/doc/run_sample_on_beaglebone_black_debian.md @@ -86,12 +86,6 @@ you obtained in the "Connecting your device to an IoT hub" step above. sudo ./c/build_all/linux/build_proton.sh --install /usr ``` -- Build a few libraries upon which the samples depend: - - ``` - sudo ~/azure-iot-sdks/c/build_all/linux/build_paho.sh - ``` - - Finally, build the sample applications: ``` diff --git a/c/doc/run_sample_on_beaglebone_black_snappy.md b/c/doc/run_sample_on_beaglebone_black_snappy.md index e62aba9c..cc86d5e4 100644 --- a/c/doc/run_sample_on_beaglebone_black_snappy.md +++ b/c/doc/run_sample_on_beaglebone_black_snappy.md @@ -227,11 +227,7 @@ To run this tool, you need connection and configuration information for your IoT sudo ~/azure-iot-sdks/c/build_all/linux/build_proton.sh --install /usr -- This SDK sample depends on the presences of a few libraries. Run the following command to build them: - - sudo ~/azure-iot-sdks/c/build_all/linux/build_paho.sh - -- You can now build the SDK code using the following command, assuming everything went OK on build\_proton.sh and build\_paho.sh +- You can now build the SDK code using the following command, assuming everything went OK on build\_proton.sh ~/azure-iot-sdks/c/build_all/linux/build.sh diff --git a/c/doc/run_sample_on_beaglebone_green.md b/c/doc/run_sample_on_beaglebone_green.md index d48dda9c..68c9a5d7 100644 --- a/c/doc/run_sample_on_beaglebone_green.md +++ b/c/doc/run_sample_on_beaglebone_green.md @@ -75,13 +75,7 @@ Before you begin you will need to create and configure an IoT hub to connect to. sudo ~/azure-iot-sdks/c/build_all/linux/build_proton.sh --install ``` -- This SDK sample depends on the presences of a few libraries. Run the following command to build them: - - ``` - sudo ~/azure-iot-sdks/c/build_all/linux/build_paho.sh - ``` - -- You can now build the SDK code using the following command, assuming everything went OK on build\_proton.sh and build\_paho.sh +- You can now build the SDK code using the following command, assuming everything went OK on build\_proton.sh ``` ~/azure-iot-sdks/c/build_all/linux/build.sh diff --git a/c/iothub_client/CMakeLists.txt b/c/iothub_client/CMakeLists.txt index 283d15e7..7be80b68 100644 --- a/c/iothub_client/CMakeLists.txt +++ b/c/iothub_client/CMakeLists.txt @@ -57,7 +57,6 @@ if(${use_mqtt}) set(iothub_client_mqtt_transport_c_files ${iothub_client_ll_transport_c_files} ./src/iothubtransportmqtt.c - ./adapters/mqttapi_paho.c ) set(iothub_client_mqtt_transport_h_files @@ -88,15 +87,33 @@ include_directories(${SHARED_UTIL_INC_FOLDER}) if(${use_http}) include_directories(${IOTHUB_CLIENT_HTTP_TRANSPORT_INC_FOLDER}) + add_library(iothub_client_http_transport + ${iothub_client_http_transport_c_files} + ${iothub_client_http_transport_h_files} + ) + linkSharedUtil(iothub_client_http_transport) endif() if(${use_amqp}) include_directories(${IOTHUB_CLIENT_AMQP_TRANSPORT_INC_FOLDER} ${PROTON_C_INCLUDES}) includeProton() + + add_definitions(-Dqpid_proton_EXPORTS) + add_library(iothub_client_amqp_transport + ${iothub_client_amqp_transport_c_files} + ${iothub_client_amqp_transport_h_files} + ) + linkSharedUtil(iothub_client_amqp_transport) endif() if(${use_mqtt}) - include_directories(${IOTHUB_CLIENT_MQTT_TRANSPORT_INC_FOLDER} $ENV{paho_path}/org.eclipse.paho.mqtt.c/src) + include_directories(${IOTHUB_CLIENT_MQTT_TRANSPORT_INC_FOLDER} ${MQTT_INC_FOLDER}) + add_library(iothub_client_mqtt_transport + ${iothub_client_mqtt_transport_c_files} + ${iothub_client_mqtt_transport_h_files} + ) + linkSharedUtil(iothub_client_mqtt_transport) + linkMqttLibrary(iothub_client_mqtt_transport) endif() include_directories(${IOTHUB_CLIENT_INC_FOLDER}) @@ -107,34 +124,6 @@ IF(WIN32) add_definitions(-DGB_MEASURE_MEMORY_FOR_THIS -DGB_DEBUG_ALLOC) ENDIF(WIN32) -if(${use_amqp}) - add_definitions(-Dqpid_proton_EXPORTS) -endif() - -if(${use_http}) - add_library(iothub_client_http_transport - ${iothub_client_http_transport_c_files} - ${iothub_client_http_transport_h_files} - ) - linkSharedUtil(iothub_client_http_transport) -endif() - -if(${use_amqp}) - add_library(iothub_client_amqp_transport - ${iothub_client_amqp_transport_c_files} - ${iothub_client_amqp_transport_h_files} - ) - linkSharedUtil(iothub_client_amqp_transport) -endif() - -if(${use_mqtt}) - add_library(iothub_client_mqtt_transport - ${iothub_client_mqtt_transport_c_files} - ${iothub_client_mqtt_transport_h_files} - ) - linkSharedUtil(iothub_client_mqtt_transport) -endif() - add_library(iothub_client ${iothub_client_c_files} ${iothub_client_h_files} diff --git a/c/iothub_client/adapters/mqttapi_paho.c b/c/iothub_client/adapters/mqttapi_paho.c deleted file mode 100644 index fd9277d4..00000000 --- a/c/iothub_client/adapters/mqttapi_paho.c +++ /dev/null @@ -1,945 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#include -#ifdef _CRTDBG_MAP_ALLOC -#include -#endif -#include "gballoc.h" - -#include "mqttapi.h" -#include "iot_logging.h" -#include "strings.h" -#include "doublylinkedlist.h" -#include "lock.h" -#include "crt_abstractions.h" -#include "sastoken.h" - -#include "MQTTClient.h" - -#define SUBSCRIBEQOS 0 -#define SENDMESSAGEQOS 1 - -#define EPOCH_TIME_T_VALUE (time_t)0 -#define SAS_TOKEN_DEFAULT_LIFETIME (3600) -#define SAS_TOKEN_DEFAULT_REFRESH_LINE (600) - -DEFINE_ENUM_STRINGS(MQTTAPI_RESULT, MQTTAPI_RESULT_VALUES); - -typedef struct MQTTAPI_TOPIC_HANDLE_DATA_TAG -{ - STRING_HANDLE topicName; - MQTTAPI_HANDLE mqttApiInstance; -} MQTTAPI_TOPIC_HANDLE_DATA, *PMQTTAPI_TOPIC_HANDLE_DATA; - -typedef struct MQTTAPI_MESSAGE_RECEIVED_LIST_TAG -{ - MQTTAPI_Message* messageReceived; - DLIST_ENTRY entry; -}MQTTAPI_MESSAGE_RECEIVED_LIST; - -typedef struct MQTTAPI_MESSAGE_SEND_LIST_TAG -{ - STRING_HANDLE topicName; - void* context; - MQTTClient_message* messageToSend; - DLIST_ENTRY entry; - MQTTClient_deliveryToken dt; -}MQTTAPI_MESSAGE_SEND_LIST; - -typedef struct MQTTTAPI_HANDLE_DATA_TAG -{ - STRING_HANDLE device_id; - - STRING_HANDLE device_key; - - STRING_HANDLE sasTokenSr; - - // Holds the expiry (seconds since the epoch) that was last used for the SAS put to the CBS - size_t lastExpiryUsed; - - // This will hold the amount of time (in seconds) that a SAS Token will have for it's expiration. - size_t sasTokenLifetime; - - // This will hold how many seconds before the expiration of a SAS token we will try to start renewing - // it. - size_t sasRefreshLine; - - bool connected; - - bool subscribed; - - PMQTTAPI_TOPIC_HANDLE_DATA subscribedTopicHandleData; - - MQTTAPI_DeliveryComplete* dcCallback; - - MQTTAPI_MessageArrived* maCallBack; - - void* maCallbackContext; - - MQTTClient client; //Saved instance - - DLIST_ENTRY messagesReceived; - - DLIST_ENTRY messagesToSend; - - DLIST_ENTRY messagesSent; - - LOCK_HANDLE LockHandle; -} MQTTTAPI_HANDLE_DATA, *PMQTTTAPI_HANDLE_DATA; - - - -static bool connectToMQTTServer(MQTTClient client, const char* username, const char* password) -{ - bool result; - MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; - MQTTClient_SSLOptions sslopts = MQTTClient_SSLOptions_initializer; - int rc; - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - conn_opts.MQTTVersion = 4; - conn_opts.username = username; - conn_opts.password = password; - - conn_opts.ssl = &sslopts; - sslopts.enableServerCertAuth = 0; - - /* Codes_SRS_MQTTAPI_04_024: [MQTTAPI_Create shall call underlying library connection functions to establish connection with the server.] */ - if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) - { - LogError("Failed to connect, MQTTClient_connect returned: %d\r\n", rc); - result = false; - } - else - { - result = true; - } - - return result; -} - - -static bool checkAndTryToConnect(PMQTTTAPI_HANDLE_DATA mqttApiState) -{ - bool result; - - if (mqttApiState != NULL) - { - if (!mqttApiState->connected) - { - /* Codes_SRS_MQTTAPI_04_062: [MQTTAPI_create shall generate SAS Token with an expiring time of 1 hour.] */ - size_t secondsSinceEpoch = (size_t)(difftime(get_time(NULL), EPOCH_TIME_T_VALUE) + 0); - size_t possibleNewExpiry = secondsSinceEpoch + mqttApiState->sasTokenLifetime; - STRING_HANDLE zeroLengthString; - - if ((zeroLengthString = STRING_new()) == NULL) - { - LogError("Could not generate zeroLenghtString for skn. \r\n"); - result = false; - } - else - { - STRING_HANDLE newSASToken = SASToken_Create(mqttApiState->device_key, mqttApiState->sasTokenSr, zeroLengthString, possibleNewExpiry); - - if (newSASToken == NULL) - { - LogError("Could not generate a SAS Token\r\n"); - result = false; - } - else - { - /* Codes_SRS_MQTTAPI_04_024: [MQTTAPI_Create shall call underlying library connection functions to establish connection with the server.] */ - if (!connectToMQTTServer(mqttApiState->client, STRING_c_str(mqttApiState->device_id), STRING_c_str(newSASToken))) - { - /* Tests_SRS_MQTTAPI_04_025: [If connection fails MQTTAPI_Create shall return NULL. */ - result = false; - } - else - { - mqttApiState->connected = true; - mqttApiState->lastExpiryUsed = possibleNewExpiry; - result = true; - } - STRING_delete(newSASToken); - } - STRING_delete(zeroLengthString); - } - } - else - { - //Here is the point that we need to check if we need to disconnect, generate a new SAS Token and Connect Again. - size_t secondsSinceEpoch; - int differenceWithLastExpiry; - secondsSinceEpoch = (size_t)(difftime(get_time(NULL), EPOCH_TIME_T_VALUE) + 0); - differenceWithLastExpiry = mqttApiState->lastExpiryUsed - secondsSinceEpoch; - - /* Codes_SRS_MQTTAPI_04_063: [DoWork shall check the SAS Token Expiration time for the current connection. If the token is near to expire and there is no pending item, it shall disconnect, generate a new SAS Token with 1 hour expiration and connect again.] */ - if ((differenceWithLastExpiry <= 0) || - (((size_t)differenceWithLastExpiry) < mqttApiState->sasRefreshLine && DList_IsListEmpty(&(mqttApiState->messagesSent)) - ) - ) // Within refresh minutes (or past if negative) of the expiration - { - /* First Disconnect */ - /* Codes_SRS_MQTTAPI_04_064: [If the token is expired we shall disconnect, signal that all pending message are failed due to Token Expired.] */ - if (MQTTClient_disconnect(mqttApiState->client, 0) != MQTTCLIENT_SUCCESS) - { - LogError("Token is Expired or about to be expired and Disconnect Failed. \r\n"); - } - else - { - size_t possibleNewExpiry = secondsSinceEpoch + mqttApiState->sasTokenLifetime; - STRING_HANDLE zeroLengthString; - - if ((zeroLengthString = STRING_new()) == NULL) - { - LogError("Could not generate zeroLenghtString for skn. \r\n"); - result = false; - } - else - { - STRING_HANDLE newSASToken = SASToken_Create(mqttApiState->device_key, mqttApiState->sasTokenSr, zeroLengthString, possibleNewExpiry); - mqttApiState->connected = false; - - if (newSASToken == NULL) - { - LogError("Could not generate a SAS Token\r\n"); - result = false; - } - else - { - /* Codes_SRS_MQTTAPI_04_024: [MQTTAPI_Create shall call underlying library connection functions to establish connection with the server.] */ - if (!connectToMQTTServer(mqttApiState->client, STRING_c_str(mqttApiState->device_id), STRING_c_str(newSASToken))) - { - /* Tests_SRS_MQTTAPI_04_025: [If connection fails MQTTAPI_Create shall return NULL. */ - result = false; - } - else - { - mqttApiState->connected = true; - mqttApiState->lastExpiryUsed = possibleNewExpiry; - if (mqttApiState->subscribed) - { - int rc; - LogInfo("Trying to Subscribe after reconnect.\r\n"); - - if ((rc = MQTTClient_subscribe(mqttApiState->client, STRING_c_str(mqttApiState->subscribedTopicHandleData->topicName), SUBSCRIBEQOS)) != MQTTCLIENT_SUCCESS) - { - LogError("Could not subscribe again. Won't be able to receive messages. Error Code: %d.\r\n", rc); - } - else - { - LogInfo("Subscribed succesfully after reconnect..\r\n"); - } - } - result = true; - } - STRING_delete(newSASToken); - } - STRING_delete(zeroLengthString); - } - } - } - - - result = true; - } - } - else - { - LogError("Invalid Arg. Handle is NULL. \r\n"); - result = false; - } - - return result; -} - - -static void connectionLost(void *context, char *cause) -{ - PMQTTTAPI_HANDLE_DATA transportState = (PMQTTTAPI_HANDLE_DATA)context; - LogError("Lost Connection, reseting Connection State. Cause: %s \r\n", cause); - - if (transportState != NULL) - { - transportState->connected = false; - } - - LogInfo("Trying to connect again\r\n"); - - if (!checkAndTryToConnect(transportState)) - { - LogError("Could not connect again. \r\n"); - } - else - { - LogInfo("Connected.\r\n"); - if (transportState->subscribed) - { - int rc; - LogInfo("Trying to Subscribe after reconnect.\r\n"); - - if ((rc = MQTTClient_subscribe(transportState->client, STRING_c_str(transportState->subscribedTopicHandleData->topicName), SUBSCRIBEQOS)) != MQTTCLIENT_SUCCESS) - { - LogError("Could not subscribe again. Won't be able to receive messages. Error Code: %d.\r\n", rc); - } - else - { - LogInfo("Subscribed succesfully after reconnect..\r\n"); - } - } - } - - if (cause != NULL) - { - MQTTClient_free(cause); - } -} - - -static void delivered(void *context, MQTTClient_deliveryToken dt) -{ - PMQTTTAPI_HANDLE_DATA transportState = (PMQTTTAPI_HANDLE_DATA)context; - - if (context != NULL) - { - //First try to find the message on the list. - PDLIST_ENTRY currentListEntry; - currentListEntry = transportState->messagesSent.Flink; - - if (currentListEntry != NULL) - { - while (currentListEntry != &transportState->messagesSent) - { - MQTTAPI_MESSAGE_SEND_LIST *mqttMessageDetailEntry = containingRecord(currentListEntry, MQTTAPI_MESSAGE_SEND_LIST, entry); - - //Identify here if the message is the one arrived. - if (mqttMessageDetailEntry->dt == dt) - { - (void)DList_RemoveEntryList(currentListEntry); //First remove the item from Waiting for Ack List. - - if (transportState->dcCallback != NULL) - { - /* Codes_SRS_MQTTAPI_04_009: [The context parameter is a point to the original value passed by MQTTAPI_PublishMessage, which contains message-specific context.] */ - /* Codes_SRS_MQTTAPI_04_052: [result contains the status of the message sent by publish.] */ - transportState->dcCallback(mqttMessageDetailEntry->context, MQTTAPI_CONFIRMATION_OK); - } - - STRING_delete(mqttMessageDetailEntry->topicName); - MQTTClient_freeMessage(&(mqttMessageDetailEntry->messageToSend)); - free(mqttMessageDetailEntry); - break; - } - currentListEntry = currentListEntry->Flink; - } - } - else - { - LogError("Error trying to access items on messagesSEnt list. Possible not initialized List.\r\n"); - } - } -} - -/* Codes_SRS_MQTTAPI_04_006: [The MQTTAPI_Message parameter contains the structure for the received message, with message payload.] */ -static int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message) -{ - MQTTAPI_MESSAGE_RECEIVED_LIST* mqttAPIMessgeEntryList; - int result; - PMQTTTAPI_HANDLE_DATA mqttApiHandleData = (PMQTTTAPI_HANDLE_DATA)context; - (void)(topicLen, topicName); - - if (mqttApiHandleData == NULL) - { - LogError("Context parameter cannot be null. Ignoring message \r\n"); - result = 1; - } - else if (mqttApiHandleData->maCallBack == NULL) - { - /* Codes_SRS_MQTTAPI_04_061: [If maCallBack is not set, MQTTAPI_MessageArrived shall return 0 to ignore received messages.] */ - result = 1; - } - else if (message == NULL) - { - LogError("message parameter cannot be null. Returning error, so it can be sent again.\r\n"); - result = 0; - } - else if ((mqttAPIMessgeEntryList = (MQTTAPI_MESSAGE_RECEIVED_LIST*)malloc(sizeof(MQTTAPI_MESSAGE_RECEIVED_LIST))) == NULL) - { - LogError("Memory Allocation Failure for MQTTAPI_Message entry list.\r\n"); - result = 0; - } - else if ((mqttAPIMessgeEntryList->messageReceived = (MQTTAPI_Message*)malloc(sizeof(MQTTAPI_Message))) == NULL) - { - LogError("Memory Allocation Failure for MQTTAPI_Message.\r\n"); - free(mqttAPIMessgeEntryList); - result = 0; - } - else - { - mqttAPIMessgeEntryList->messageReceived->payloadlen = message->payloadlen; - - if ((mqttAPIMessgeEntryList->messageReceived->payload = (unsigned char*)malloc(mqttAPIMessgeEntryList->messageReceived->payloadlen)) == NULL) - { - LogError("Memory allocation error.\r\n"); - free(mqttAPIMessgeEntryList->messageReceived); - free(mqttAPIMessgeEntryList); - result = 0; - } - else - { - (void)memcpy(mqttAPIMessgeEntryList->messageReceived->payload, message->payload, message->payloadlen); - if (Lock(mqttApiHandleData->LockHandle) == LOCK_OK) - { - DList_InsertHeadList(&(mqttApiHandleData->messagesReceived), &(mqttAPIMessgeEntryList->entry)); - Unlock(mqttApiHandleData->LockHandle); - result = 1; - } - else - { - LogError("Problem Aquiring Lock to add message received on the list.\r\n"); - free(mqttAPIMessgeEntryList->messageReceived->payload); - free(mqttAPIMessgeEntryList->messageReceived); - free(mqttAPIMessgeEntryList); - result = 0; - } - } - } - - //We just free the MQTTClient Message if it was succesfully received, otherwise MQTTClient will call this with a corrupted message. - if (message != NULL && result == 1) - { - MQTTClient_freeMessage(&message); - } - - return result; -} - - -MQTTAPI_HANDLE MQTTAPI_Create(const MQTTAPI_ConnectOptions* options) -{ - PMQTTTAPI_HANDLE_DATA result; - - /* Codes_SRS_MQTTAPI_04_011: [If any member of the parameter options is NULL or empty then MQTTAPI_Create shall return NULL.] */ - if (options == NULL) - { - LogError("Invalid Argument. options cannot be NULL.\r\n") - result = NULL; - } - else if (options->deviceId == NULL || strlen(options->deviceId) <= 0) - { - LogError("Invalid Argument. Device Id cannot be NULL or Empty.\r\n") - result = NULL; - } - else if (options->deviceKey == NULL || strlen(options->deviceKey) <= 0) - { - LogError("Invalid Argument. Device Key cannot be NULL or Empty.\r\n") - result = NULL; - } - else if (options->serverURI == NULL || strlen(options->serverURI) <= 0) - { - LogError("Invalid Argument. Device Key cannot be NULL or Empty.\r\n") - result = NULL; - } - else if (options->sasTokenSr == NULL || strlen(options->sasTokenSr) <= 0) - { - LogError("Invalid Argument. sasTokenSr cannot be NULL or Empty.\r\n") - result = NULL; - } - /* Tests_SRS_MQTTAPI_04_014: [Otherwise, MQTTAPI_Create shall return a MQTTAPI_HANDLE suitable for further calls to the module.] */ - else - { - result = (PMQTTTAPI_HANDLE_DATA)malloc(sizeof(MQTTTAPI_HANDLE_DATA)); - - if (result != NULL) - { - result->connected = false; - result->subscribed = false; - result->dcCallback = NULL; - result->maCallBack = NULL; - result->maCallbackContext = NULL; - result->subscribedTopicHandleData = NULL; - result->sasTokenLifetime = SAS_TOKEN_DEFAULT_LIFETIME; - result->sasRefreshLine = SAS_TOKEN_DEFAULT_REFRESH_LINE; - - DList_InitializeListHead(&(result->messagesReceived)); - DList_InitializeListHead(&(result->messagesToSend)); - DList_InitializeListHead(&(result->messagesSent)); - - if ((result->LockHandle = Lock_Init()) == NULL) - { - LogError("Lock_Init failed\r\n"); - free(result); - result = NULL; - } - /* Codes_SRS_MQTTAPI_04_012: [Parameters deviceId, deviceKey and sasTokenSr shall be saved.] */ - else if ((result->device_id = STRING_construct(options->deviceId)) == NULL) - { - /* Codes_SRS_MQTTAPI_04_013: [If saving these parameters fail for any reason MQTTAPI_Create shall return NULL.] */ - LogError("Could not create deviceId String.\r\n"); - Lock_Deinit(result->LockHandle); - free(result); - result = NULL; - } - /* Codes_SRS_MQTTAPI_04_012: [Parameters deviceId, deviceKey and sasTokenSr shall be saved.] */ - else if ((result->device_key = STRING_construct(options->deviceKey)) == NULL) - { - /* Codes_SRS_MQTTAPI_04_013: [If saving these parameters fail for any reason MQTTAPI_Create shall return NULL.] */ - LogError("Could not create deviceId String.\r\n"); - STRING_delete(result->device_id); - Lock_Deinit(result->LockHandle); - free(result); - result = NULL; - } - /* Codes_SRS_MQTTAPI_04_012: [Parameters deviceId, deviceKey and sasTokenSr shall be saved.] */ - else if ((result->sasTokenSr = STRING_construct(options->sasTokenSr)) == NULL) - { - LogError("Could not create sasTokenSr String.\r\n"); - STRING_delete(result->device_key); - STRING_delete(result->device_id); - Lock_Deinit(result->LockHandle); - free(result); - result = NULL; - } - else if (MQTTClient_create(&result->client, options->serverURI, STRING_c_str(result->device_id), - MQTTCLIENT_PERSISTENCE_NONE, NULL) != MQTTCLIENT_SUCCESS) - { - LogError("Could not create MQTT Client.\r\n"); - STRING_delete(result->sasTokenSr); - STRING_delete(result->device_key); - STRING_delete(result->device_id); - Lock_Deinit(result->LockHandle); - free(result); - result = NULL; - } - /* Codes_SRS_MQTTAPI_04_004: [This function is registered when the user makes a call to MQTTAPI_SetCallbacks.] */ - /* Codes_SRS_MQTTAPI_04_005: [The context parameter is a pointer to the original value passed by MQTTAPI_SetCallbacks, which contains application-specific context.] */ - /* Codes_SRS_MQTTAPI_04_008: [This function is registered when the user makes a call to MQTTAPI_SetCallbacks.] */ - else if (MQTTClient_setCallbacks(result->client, result, connectionLost, msgarrvd, delivered) != MQTTCLIENT_SUCCESS) - { - LogError("Could not set callbacks.\r\n"); - STRING_delete(result->sasTokenSr); - STRING_delete(result->device_key); - STRING_delete(result->device_id); - MQTTClient_destroy(&result->client); - Lock_Deinit(result->LockHandle); - free(result); - result = NULL; - } - /* Codes_SRS_MQTTAPI_04_024: [MQTTAPI_Create shall call underlying library connection functions to establish connection with the server.] */ - /* Codes_SRS_MQTTAPI_04_047: [Otherwise MQTTAPI_Create shall return a non-NULL MQTTAPI_HANDLE] */ - else if (!checkAndTryToConnect(result)) - { - /* Codes_SRS_MQTTAPI_04_025: [If connection fails MQTTAPI_Create shall return NULL. */ - LogError("Could not Connect to MQTT Server.\r\n"); - STRING_delete(result->sasTokenSr); - STRING_delete(result->device_key); - STRING_delete(result->device_id); - MQTTClient_destroy(&result->client); - Lock_Deinit(result->LockHandle); - free(result); - result = NULL; - } - - } - else - { - /* Codes_SRS_MQTTAPI_04_015: [If creating instance fails for any reason, then MQTTAPI_Create shall return NULL.] */ - LogError("Could not create MQTT API handle data. Memory allocation failed.\r\n"); - result = NULL; - } - } - - return (MQTTAPI_HANDLE)result; -} - -MQTTAPI_RESULT MQTTAPI_SetMessageCallback(MQTTAPI_HANDLE instance, void* context, MQTTAPI_MessageArrived* ma) -{ - MQTTAPI_RESULT result; - /* Codes_SRS_MQTTAPI_04_016: [If instance parameter is NULL, setMessageCallback shall return MQTTAPI_INVALID_ARG.] */ - if (instance == NULL) - { - LogError("Invalid Argument. instance cannot be NULL.\r\n") - result = MQTTAPI_INVALID_ARG; - } - else - { - PMQTTTAPI_HANDLE_DATA mqttapi_handle_data = (PMQTTTAPI_HANDLE_DATA)instance; - /* Codes_SRS_MQTTAPI_04_020: [If while saving the callbacks fails setMessageCallback shall return MQTTAPI_ERROR, otherwise it shall return MQTTAPI_OK] */ - /* Codes_SRS_MQTTAPI_04_019: [If any of the callback pointers are different than NULL it will be saved.] */ - /* Codes_SRS_MQTTAPI_04_018: [If parameter context is not NULL, it will be saved and passed to the user when any of the callback is trigerred.] */ - if (ma != NULL) - { - mqttapi_handle_data->maCallBack = ma; - mqttapi_handle_data->maCallbackContext = context; - result = MQTTAPI_OK; - } - else - { - LogError("Could not set because dc parameter cannot be NULL. \r\n"); - result = MQTTAPI_ERROR; - } - } - - return result; -} - -MQTTAPI_RESULT MQTTAPI_SetDeliveryCompletedCallback(MQTTAPI_HANDLE instance, MQTTAPI_DeliveryComplete* dc) -{ - MQTTAPI_RESULT result; - - /* Codes_SRS_MQTTAPI_04_054: [If instance parameter is NULL, MQTTAPI_SetDeliveryCompletedCallback shall return MQTTAPI_INVALID_ARG.] */ - if (instance == NULL) - { - LogError("Invalid Argument. instance cannot be NULL.\r\n") - result = MQTTAPI_INVALID_ARG; - } - else - { - PMQTTTAPI_HANDLE_DATA mqttapi_handle_data = (PMQTTTAPI_HANDLE_DATA)instance; - /* Codes_SRS_MQTTAPI_04_056: [If while saving the callbacks fails MQTTAPI_SetDeliveryCompletedCallback shall return MQTTAPI_ERROR] */ - if (dc != NULL) - { - mqttapi_handle_data->dcCallback = dc; - result = MQTTAPI_OK; - } - else - { - /* Codes_SRS_MQTTAPI_04_057: [otherwise it shall return MQTTAPI_OK] */ - LogError("Could not set because dc parameter cannot be NULL. \r\n"); - result = MQTTAPI_ERROR; - } - } - - return result; -} - - -void MQTTAPI_Destroy(MQTTAPI_HANDLE instance) -{ - PMQTTTAPI_HANDLE_DATA mqttHandleData = (PMQTTTAPI_HANDLE_DATA)instance; - - /* Codes_SRS_MQTTAPI_04_021: [If parameter instance is NULL then MQTTAPI_Destroy shall take no action.] */ - if (mqttHandleData != NULL) - { - /* Codes_SRS_MQTTAPI_04_022: [MQTTAPI_Destroy shall free all resources used by MQTTAPI_HANDLE.] */ - STRING_delete(mqttHandleData->device_id); - STRING_delete(mqttHandleData->device_key); - STRING_delete(mqttHandleData->sasTokenSr); - /* Codes_SRS_MQTTAPI_04_049: [If the instance is connected, MQTTAPI_Destroy shall disconnect the instance] */ - if (mqttHandleData->subscribed) - { - MQTTAPI_Unsubscribe(mqttHandleData->subscribedTopicHandleData); - } - - if (mqttHandleData->connected) - { - MQTTClient_disconnect(mqttHandleData->client, 0); - } - - /* Codes_SRS_MQTTAPI_04_053: [If there are messages to be sent MQTTAPI_Destroy shall signal the user that the message couldnt be sent by reason of MQTTAPI_CONFIRMATION_BECAUSE_DESTROY] */ - { - PDLIST_ENTRY received; - while ((received = DList_RemoveHeadList(&(mqttHandleData->messagesReceived))) != &(mqttHandleData->messagesReceived)) - { - MQTTAPI_MESSAGE_RECEIVED_LIST* temp = containingRecord(received, MQTTAPI_MESSAGE_RECEIVED_LIST, entry); - if (mqttHandleData->maCallBack != NULL) - { - if (!mqttHandleData->maCallBack(mqttHandleData->maCallbackContext, temp->messageReceived)) - { - LogError("Client could not handle message, dropping it."); - } - } - - free(temp->messageReceived->payload); - free(temp->messageReceived); - free(temp); - } - } - - { - PDLIST_ENTRY messageToSend; - while ((messageToSend = DList_RemoveHeadList(&(mqttHandleData->messagesToSend))) != &(mqttHandleData->messagesToSend)) - { - MQTTAPI_MESSAGE_SEND_LIST* temp = containingRecord(messageToSend, MQTTAPI_MESSAGE_SEND_LIST, entry); - - if (mqttHandleData->dcCallback != NULL) - { - mqttHandleData->dcCallback(temp->context, MQTTAPI_CONFIRMATION_BECAUSE_DESTROY); - MQTTClient_freeMessage(&(temp->messageToSend)); - free(temp->messageToSend); - STRING_delete(temp->topicName); - free(temp); - } - } - } - - { - PDLIST_ENTRY currentListEntry; - while ((currentListEntry = DList_RemoveHeadList(&(mqttHandleData->messagesSent))) != &(mqttHandleData->messagesSent)) - { - MQTTAPI_MESSAGE_SEND_LIST* temp = containingRecord(currentListEntry, MQTTAPI_MESSAGE_SEND_LIST, entry); - - if (mqttHandleData->dcCallback != NULL) - { - mqttHandleData->dcCallback(temp->context, MQTTAPI_CONFIRMATION_BECAUSE_DESTROY); - MQTTClient_freeMessage(&(temp->messageToSend)); - free(temp->messageToSend); - STRING_delete(temp->topicName); - free(temp); - } - } - } - - MQTTClient_destroy(&mqttHandleData->client); - Lock_Deinit(mqttHandleData->LockHandle); - free(mqttHandleData); - } -} - - -MQTTAPI_RESULT MQTTAPI_PublishMessage(MQTTAPI_HANDLE instance, const char* topicName, const MQTTAPI_Message* msg, void* context) -{ - MQTTAPI_RESULT result; - PMQTTTAPI_HANDLE_DATA mqttApiHandleData = (PMQTTTAPI_HANDLE_DATA)instance; - - /* Codes_SRS_MQTTAPI_04_038: [If any of the parameter is NULL, MQTTAPI_PublishMessage shall return MQTTAPI_INVALID_ARG.] */ - if (instance == NULL) - { - LogError("Invalid Argument. instance can't be null.\r\n"); - result = MQTTAPI_INVALID_ARG; - } - /* Codes_SRS_MQTTAPI_04_038: [If any of the parameter is NULL, MQTTAPI_PublishMessage shall return MQTTAPI_INVALID_ARG.] */ - else if (topicName == NULL || strlen(topicName) <= 0) - { - LogError("Invalid Argument. topicName can't be null or empty.\r\n"); - result = MQTTAPI_INVALID_ARG; - } - /* Codes_SRS_MQTTAPI_04_038: [If any of the parameter is NULL, MQTTAPI_PublishMessage shall return MQTTAPI_INVALID_ARG.] */ - else if (msg == NULL) - { - LogError("Invalid Argument. msg can't be null.\r\n"); - result = MQTTAPI_INVALID_ARG; - } - /* Codes_SRS_MQTTAPI_04_059: [If DeliveryCompleted callback is not set publishMessage shall return MQTTAPI_ERROR.] */ - else if (mqttApiHandleData->dcCallback == NULL) - { - LogError("Error Sending data, missind Delivery Completed callback to be set.\r\n"); - result = MQTTAPI_ERROR; - } - else - { - MQTTAPI_MESSAGE_SEND_LIST* mqttApiMessageEntryList; - - /* Codes_SRS_MQTTAPI_04_039: [MQTTAPI_PublishMessage shall create structure needed to send a message to the topic described by the topicName parameter.] */ - if ((mqttApiMessageEntryList = (MQTTAPI_MESSAGE_SEND_LIST*)malloc(sizeof(MQTTAPI_MESSAGE_SEND_LIST))) == NULL) - { - LogError("Memmory Allocation failure to create mqttApi Message.\r\n"); - result = MQTTAPI_ERROR; - } - else if ((mqttApiMessageEntryList->topicName = STRING_construct(topicName)) == NULL) -{ - LogError("Could not create topicName String.\r\n"); - free(mqttApiMessageEntryList); - result = MQTTAPI_ERROR; -} - else - { - MQTTClient_message *pubmsg = (MQTTClient_message *)malloc(sizeof(MQTTClient_message)); - - if (pubmsg == NULL) - { - LogError("Memory Allocation Failure to create MQTTClient_message.\r\n"); - STRING_delete(mqttApiMessageEntryList->topicName); - free(mqttApiMessageEntryList); - result = MQTTAPI_ERROR; - } - else - { - pubmsg->struct_id[0] = 'M'; - pubmsg->struct_id[1] = 'Q'; - pubmsg->struct_id[2] = 'T'; - pubmsg->struct_id[3] = 'M'; - pubmsg->struct_version = 0; - pubmsg->qos = SENDMESSAGEQOS; - pubmsg->retained = 0; - pubmsg->dup = 0; - pubmsg->msgid = 0; - pubmsg->payloadlen = msg->payloadlen; - - /* Codes_SRS_MQTTAPI_04_043: [MQTTAPI_PublishMessage shall clone MQTTAPI_Message so the user can free it after calling publishMessage.] */ - if ((pubmsg->payload = malloc(msg->payloadlen)) == NULL) - { - LogError("Memory Allocation Failure to create MQTTClient_message.\r\n"); - free(pubmsg); - STRING_delete(mqttApiMessageEntryList->topicName); - free(mqttApiMessageEntryList); - result = MQTTAPI_ERROR; - } - else -{ - (void)memcpy(pubmsg->payload, msg->payload, msg->payloadlen); - /* Codes_SRS_MQTTAPI_04_058: [If context is not NULL it shall be stored and passed to the user when received callback function is called.] */ - mqttApiMessageEntryList->context = context; - mqttApiMessageEntryList->messageToSend = pubmsg; - DList_InsertHeadList(&(mqttApiHandleData->messagesToSend), &(mqttApiMessageEntryList->entry)); - - /* Codes_SRS_MQTTAPI_04_048: [If the message was correctly queued (on its on a queue on underlying library) MQTTAPI_PublishMessage shall return MQTTAPI_OK.] */ - result = MQTTAPI_OK; - } - } - } - } - - return result; -} - - -MQTTAPI_TOPIC_HANDLE MQTTAPI_Subscribe(MQTTAPI_HANDLE instance, const char* topic) -{ - PMQTTTAPI_HANDLE_DATA handle = instance; - PMQTTAPI_TOPIC_HANDLE_DATA result; - - /* Codes_SRS_MQTTAPI_04_029: [If any of the parameters instance or topic is NULL MQTTAPI_Subscribe shall return NULL.] */ - if (instance == NULL || topic == NULL || strlen(topic) == 0) - { - result = NULL; - } - else - { - if ((result = (PMQTTAPI_TOPIC_HANDLE_DATA)malloc(sizeof(MQTTAPI_TOPIC_HANDLE_DATA))) == NULL) - { - LogError("Memory Allocation failure to store Topic Handle Data.\r\n"); - handle->subscribed = false; - } - else if (checkAndTryToConnect(handle)) - { - int rc; - /* Codes_SRS_MQTTAPI_04_031: [MQTTAPI_Subscribe shall call underlying library methods to subscribe to the topic on the topic parameter.] */ - if ((rc = MQTTClient_subscribe(handle->client, topic, SUBSCRIBEQOS)) != MQTTCLIENT_SUCCESS) - { - /* Codes_SRS_MQTTAPI_04_032: [If the underlying library fails MQTTAPI_Subscribe shall return NULL] */ - LogError("Error subscribing to topic. Code is:%d \r\n", rc); - free(result); - result = NULL; - handle->subscribed = false; - } - else - { - /* Codes_SRS_MQTTAPI_04_033: [Otherwise MQTTAPI_Subscribe shall return a non-NULL MQTTAPI_TOPIC_HANDLE] */ - result->mqttApiInstance = handle; - if ((result->topicName = STRING_construct(topic)) == NULL) - { - LogError("Problem to save topic name.\r\n"); - free(result); - result = NULL; - handle->subscribed = false; - } - else - { - handle->subscribedTopicHandleData = result; - handle->subscribed = true; - } - } - } - else - { - LogError("MQTT Client Not Connected. Error trying to reconect.\r\n"); - free(result); - result = NULL; - } - } - - return result; -} - -void MQTTAPI_Unsubscribe(MQTTAPI_TOPIC_HANDLE topicInstance) -{ - /* Codes_SRS_MQTTAPI_04_034: [If topicInstance is NULL MQTTAPI_Unsubscribe shall do nothing.] */ - if (topicInstance != NULL) - { - PMQTTAPI_TOPIC_HANDLE_DATA topicHandleData = topicInstance; - PMQTTTAPI_HANDLE_DATA mqttApiInstance = topicHandleData->mqttApiInstance; - - /* Codes_SRS_MQTTAPI_04_035: [MQTTAPI_Unsubscribe shall call underlying library methods to unsubscribe to the topic Instance.] */ - if (MQTTClient_unsubscribe(mqttApiInstance->client, STRING_c_str(topicHandleData->topicName)) != MQTTCLIENT_SUCCESS) - { - LogError("Problems on Unsubscribing to Commands.\r\n"); - } - else -{ - mqttApiInstance->subscribed = false; - /* Codes_SRS_MQTTAPI_04_060: [MQTTAPI_Unsubscribe shall release all previously allocated resources pointed by topicInstance.] */ - STRING_delete(mqttApiInstance->subscribedTopicHandleData->topicName); - free(mqttApiInstance->subscribedTopicHandleData); - } - } -} - -void MQTTAPI_DoWork(MQTTAPI_HANDLE instance) -{ - PMQTTTAPI_HANDLE_DATA handle = instance; - - /* Codes_SRS_MQTTAPI_04_050: [if parameter instance is NULL then MQTTAPI_DoWork shall not perform any action.] */ - if (handle != NULL) - { - - if (!checkAndTryToConnect(handle)) - { - LogError("Client Not Connected and could not connect.\r\n"); - } - else - { - if (Lock(handle->LockHandle) == LOCK_OK) - { - - //message - { - PDLIST_ENTRY received; - while ((received = DList_RemoveHeadList(&(handle->messagesReceived))) != &(handle->messagesReceived)) - { - MQTTAPI_MESSAGE_RECEIVED_LIST* temp = containingRecord(received, MQTTAPI_MESSAGE_RECEIVED_LIST, entry); - if (handle->maCallBack != NULL) - { - if (!handle->maCallBack(handle->maCallbackContext, temp->messageReceived)) - { - LogError("Client could not handle message, dropping it."); - } - } - - free(temp->messageReceived->payload); - free(temp->messageReceived); - free(temp); - } - } - Unlock(handle->LockHandle); - } - else - { - LogError("Could not aquire lock for message.\r\n"); - } - - //Event - { - PDLIST_ENTRY messageToSend; - while ((messageToSend = DList_RemoveHeadList(&(handle->messagesToSend))) != &(handle->messagesToSend)) - { - MQTTAPI_MESSAGE_SEND_LIST* temp = containingRecord(messageToSend, MQTTAPI_MESSAGE_SEND_LIST, entry); - - if (MQTTClient_publishMessage(handle->client, STRING_c_str(temp->topicName), temp->messageToSend, &(temp->dt)) != MQTTCLIENT_SUCCESS) - { - handle->dcCallback(temp->context, MQTTAPI_CONFIRMATION_ERROR); - MQTTClient_freeMessage(&(temp->messageToSend)); - free(temp->messageToSend); - STRING_delete(temp->topicName); - free(temp); - } - else - { - DList_InsertTailList(&(handle->messagesSent), &(temp->entry)); - } - } - } - } - } - -} \ No newline at end of file diff --git a/c/iothub_client/devdoc/requirement_docs/iothubmqtttransport_requirements.docm b/c/iothub_client/devdoc/requirement_docs/iothubmqtttransport_requirements.docm deleted file mode 100644 index 1619098d..00000000 Binary files a/c/iothub_client/devdoc/requirement_docs/iothubmqtttransport_requirements.docm and /dev/null differ diff --git a/c/iothub_client/devdoc/requirement_docs/iothubmqtttransport_requirements.md b/c/iothub_client/devdoc/requirement_docs/iothubmqtttransport_requirements.md index 0cd28455..a183109f 100644 --- a/c/iothub_client/devdoc/requirement_docs/iothubmqtttransport_requirements.md +++ b/c/iothub_client/devdoc/requirement_docs/iothubmqtttransport_requirements.md @@ -20,3 +20,82 @@ extern IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_SetOption(TRANSPORT_HANDLE handl extern const void* MQTT_Protocol(void); ``` +##IoTHubTransportMqtt_Create +``` +TRANSPORT_HANDLE IoTHubTransportMqtt_Create(const IOTHUBTRANSPORT_CONFIG* config) +``` +IoTHubTransportMqtt_Create shall create a TRANSPORT_HANDLE that can be further used in the calls to this module’s APIS. + +**SRS_IOTHUB_MQTT_TRANSPORT_07_001: [**If parameter config is NULL then IoTHubTransportMqtt_Create shall return NULL.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_002: [**If the parameter config's variables upperConfig or waitingToSend are NULL then IoTHubTransportMqtt_Create shall return NULL.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_003: [**If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_004: [**If the config's waitingToSend variable is NULL then IoTHubTransportMqtt_Create shall return NULL.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_005: [**If the upperConfig's variables deviceKey, iotHubName, or iotHubSuffix are empty strings then IoTHubTransportMqtt_Create shall return NULL.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_006: [**If the upperConfig's variables deviceId is an empty strings or length is greater then 128 then IoTHubTransportMqtt_Create shall return NULL.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_007: [**If the upperConfig's variables protocolGatewayHostName is non-Null and the length is an empty string then IoTHubTransportMqtt_Create shall return NULL.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_008: [**If the upperConfig contains a valid protocolGatewayHostName value the this shall be used for the hostname, otherwise the hostname shall be constructed using the iothubname and iothubSuffix.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_009: [**If any error is encountered then IoTHubTransportMqtt_Create shall return NULL.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_010: [**IoTHubTransportMqtt_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key, sasTokenSr and client handle shall be saved.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_011: [**On Success IoTHubTransportMqtt_Create shall return a non-NULL value.**]** + +##IoTHubTransportMqtt_Destroy +``` +void IoTHubTransportMqtt_Destroy(TRANSPORT_HANDLE handle) +``` +**SRS_IOTHUB_MQTT_TRANSPORT_07_012: [**IoTHubTransportMqtt_Destroy shall do nothing if parameter handle is NULL.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_013: [**If the parameter subscribe is true then IoTHubTransportMqtt_Destroy shall call IoTHubTransportMqtt_Unsubscribe.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_014: [**IoTHubTransportMqtt_Destroy shall free all the resources currently in use.**]** + +##IoTHubTransportMqtt_Subscribe +``` +int IoTHubTransportMqtt_Subscribe(TRANSPORT_HANDLE handle) +``` +**SRS_IOTHUB_MQTT_TRANSPORT_07_015: [**If parameter handle is NULL than IoTHubTransportMqtt_Subscribe shall return a non-zero value.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_016: [**IoTHubTransportMqtt_Subscribe shall call mqtt_client_subscribe to subscribe to the Message Topic.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_017: [**Upon failure IoTHubTransportMqtt_Subscribe shall return a non-zero value.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_018: [**On success IoTHubTransportMqtt_Subscribe shall return 0.**]** + +##IoTHubTransportMqtt_Unsubscribe +``` +void IoTHubTransportMqtt_Unsubscribe(TRANSPORT_HANDLE handle) +``` +**SRS_IOTHUB_MQTT_TRANSPORT_07_019: [**If parameter handle is NULL then IoTHubTransportMqtt_Unsubscribe shall do nothing.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_020: [**IoTHubTransportMqtt_Unsubscribe shall call mqtt_client_unsubscribe to unsubscribe the mqtt message topic.**]** + +##IoTHubTransportMqtt_DoWork +``` +void IoTHubTransportMqtt_DoWork(TRANSPORT_HANDLE handle, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle) +``` +**SRS_IOTHUB_MQTT_TRANSPORT_07_026: [**IoTHubTransportMqtt_DoWork shall do nothing if parameter handle and/or iotHubClientHandle is NULL.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_027: [**IoTHubTransportMqtt_DoWork shall inspect the “waitingToSend” DLIST passed in config structure.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_028: [**IoTHubTransportMqtt_DoWork shall retrieve the payload message from the messageHandle parameter.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_029: [**IoTHubTransportMqtt_DoWork shall create a MQTT_MESSAGE_HANDLE and pass this to a call to mqtt_client_publish.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_030: [**IoTHubTransportMqtt_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.**]** + +##IoTHubTransportMqtt_GetSendStatus +``` +IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_GetSendStatus(TRANSPORT_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus) +``` +**SRS_IOTHUB_MQTT_TRANSPORT_07_023: [**IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_024: [**IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_025: [**IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.**]** + +##IoTHubTransportMqtt_SetOption +``` +IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_SetOption(TRANSPORT_HANDLE handle, const char* optionName, const void* value) +``` +**SRS_IOTHUB_MQTT_TRANSPORT_07_021: [**If any parameter is NULL then IoTHubTransportMqtt_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_031: [**If the option parameter is set to "logtrace" then the value shall be a bool_ptr and the value will determine if the mqtt client log is on or off.**]** +**SRS_IOTHUB_MQTT_TRANSPORT_07_032: [**IoTHubTransportMqtt_SetOption shall return IOTHUB_CLIENT_INVALID_ARG if the option parameter is not a known option string.**]** + +##MQTT_Protocol +``` +const void* MQTT_Protocol(void) +``` +**SRS_IOTHUB_MQTT_TRANSPORT_07_022: [**This function shall return a pointer to a structure of type TRANSPORT_PROVIDER having the following values for it’s fields: +IoTHubTransport_Create = IoTHubTransportMqtt_Create +IoTHubTransport_Destroy = IoTHubTransportMqtt_Destroy +IoTHubTransport_Subscribe = IoTHubTransportMqtt_Subscribe +IoTHubTransport_Unsubscribe = IoTHubTransportMqtt_Unsubscribe +IoTHubTransport_DoWork = IoTHubTransportMqtt_DoWork +IoTHubTransport_SetOption = IoTHubTransportMqtt_SetOption**]** diff --git a/c/iothub_client/inc/iothub_client_ll.h b/c/iothub_client/inc/iothub_client_ll.h index 395e1bc5..267cefa0 100644 --- a/c/iothub_client/inc/iothub_client_ll.h +++ b/c/iothub_client/inc/iothub_client_ll.h @@ -29,6 +29,8 @@ #include "iothub_message.h" +#include "xio.h" + #ifdef __cplusplus extern "C" { @@ -85,30 +87,34 @@ typedef void* IOTHUB_CLIENT_LL_HANDLE; typedef void(*IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK)(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback); typedef IOTHUBMESSAGE_DISPOSITION_RESULT (*IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC)(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback); typedef const void*(*IOTHUB_CLIENT_TRANSPORT_PROVIDER)(void); +typedef const XIO_HANDLE (*IO_TRANSPORT_PROVIDER_CALLBACK)(const char* fqdn, int port); /** @brief This struct captures IoTHub client configuration. */ typedef struct IOTHUB_CLIENT_CONFIG_TAG { - /** @brief A function pointer that is passed into the @c IoTHubClientCreate. - * A function definition for AMQP, @c DeviceClientProvideAmqpResources, - * is defined in the include @c iothubtransportamqp.h. A function - * definition for HTTP, @c DeviceClientProvideHttpResources, is defined - * in the include @c iothubtransporthttp.h */ + /** @brief A function pointer that is passed into the @c IoTHubClientCreate. + * A function definition for AMQP, @c DeviceClientProvideAmqpResources, + * is defined in the include @c iothubtransportamqp.h. A function + * definition for HTTP, @c DeviceClientProvideHttpResources, is defined + * in the include @c iothubtransporthttp.h */ IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; /** @brief A string that identifies the device. */ const char* deviceId; - /** @brief The device key used to authenticate the device. */ + /** @brief The device key used to authenticate the device. */ const char* deviceKey; /** @brief The IoT Hub name to which the device is connecting. */ const char* iotHubName; - /** @brief IoT Hub suffix goes here, e.g., private.azure-devices-int.net. */ + /** @brief IoT Hub suffix goes here, e.g., private.azure-devices-int.net. */ const char* iotHubSuffix; const char* protocolGatewayHostName; + + /** @brief A callback function to provide the IO transport instance, e.g. SChannel, OpenSSL or WebSockets. */ + IO_TRANSPORT_PROVIDER_CALLBACK io_transport_provider_callback; } IOTHUB_CLIENT_CONFIG; /** diff --git a/c/iothub_client/samples/iothub_client_sample_mqtt/CMakeLists.txt b/c/iothub_client/samples/iothub_client_sample_mqtt/CMakeLists.txt index e4bc0b65..5d419392 100644 --- a/c/iothub_client/samples/iothub_client_sample_mqtt/CMakeLists.txt +++ b/c/iothub_client/samples/iothub_client_sample_mqtt/CMakeLists.txt @@ -4,29 +4,29 @@ #this is CMakeLists.txt for iothub_client_sample_mqtt if(NOT ${use_mqtt}) - message(FATAL_ERROR "iothub_client_sample_mqtt being generated without mqtt support") + message(FATAL_ERROR "iothub_client_sample_mqtt being generated without mqtt support") endif() compileAsC99() set(iothub_client_sample_mqtt_c_files -iothub_client_sample_mqtt.c + iothub_client_sample_mqtt.c ) if(WIN32) - set(iothub_client_sample_mqtt_c_files ${iothub_client_sample_mqtt_c_files} ./windows/main.c) + set(iothub_client_sample_mqtt_c_files ${iothub_client_sample_mqtt_c_files} ./windows/main.c) else() - set(iothub_client_sample_mqtt_c_files ${iothub_client_sample_mqtt_c_files} ./linux/main.c) + set(iothub_client_sample_mqtt_c_files ${iothub_client_sample_mqtt_c_files} ./linux/main.c) endif() set(iothub_client_sample_mqtt_h_files -iothub_client_sample_mqtt.h + iothub_client_sample_mqtt.h ) IF(WIN32) - #windows needs this define - add_definitions(-D_CRT_SECURE_NO_WARNINGS) - add_definitions(-DGB_MEASURE_MEMORY_FOR_THIS -DGB_DEBUG_ALLOC) + #windows needs this define + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + add_definitions(-DGB_MEASURE_MEMORY_FOR_THIS -DGB_DEBUG_ALLOC) ENDIF(WIN32) include_directories(.) @@ -34,10 +34,7 @@ include_directories(.) add_executable(iothub_client_sample_mqtt ${iothub_client_sample_mqtt_c_files} ${iothub_client_sample_mqtt_h_files}) target_link_libraries(iothub_client_sample_mqtt - iothub_client_mqtt_transport - iothub_client - iothub_client_mqtt_transport + iothub_client_mqtt_transport + iothub_client ) -linkSharedUtil(iothub_client_sample_mqtt) -linkPaho(iothub_client_sample_mqtt) \ No newline at end of file diff --git a/c/iothub_client/samples/iothub_client_sample_mqtt/iothub_client_sample_mqtt.c b/c/iothub_client/samples/iothub_client_sample_mqtt/iothub_client_sample_mqtt.c index d9c4b5e6..f0d949f8 100644 --- a/c/iothub_client/samples/iothub_client_sample_mqtt/iothub_client_sample_mqtt.c +++ b/c/iothub_client/samples/iothub_client_sample_mqtt/iothub_client_sample_mqtt.c @@ -9,11 +9,23 @@ #include "threadapi.h" #include "crt_abstractions.h" #include "iothubtransportmqtt.h" +#if _WIN32 +#include "tlsio_schannel.h" +#else +#ifdef MBED_BUILD_TIMESTAMP +#include "tlsio_wolfssl.h" +#else +#include "tlsio_openssl.h" +#endif +#endif +#include "platform.h" /*String containing Hostname, Device Id & Device Key in the format: */ /* "HostName=;DeviceId=;SharedAccessKey=" */ static const char* connectionString = "[device connection string]"; static int callbackCounter; +static char msgText[1024]; +#define MESSAGE_COUNT 5 DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_CONFIRMATION_RESULT, IOTHUB_CLIENT_CONFIRMATION_RESULT_VALUES); @@ -23,6 +35,25 @@ typedef struct EVENT_INSTANCE_TAG int messageTrackingId; // For tracking the messages within the user callback. } EVENT_INSTANCE; +const void* io_transport_provider(const char* fqdn, int port) +{ + const IO_INTERFACE_DESCRIPTION* io_interface_description; + +#ifdef _WIN32 + TLSIO_SCHANNEL_CONFIG tls_io_config = { fqdn, port }; + io_interface_description = tlsio_schannel_get_interface_description(); +#else + #ifdef MBED_BUILD_TIMESTAMP + TLSIO_WOLFSSL_CONFIG tls_io_config = { fqdn, port }; + io_interface_description = tlsio_wolfssl_get_interface_description(); + #else + TLSIO_OPENSSL_CONFIG tls_io_config = { fqdn, port }; + io_interface_description = tlsio_openssl_get_interface_description(); + #endif +#endif + return (void*)xio_create(io_interface_description, &tls_io_config, NULL); +} + static IOTHUBMESSAGE_DISPOSITION_RESULT ReceiveMessageCallback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback) { int* counter = (int*)userContextCallback; @@ -73,9 +104,6 @@ static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, v IoTHubMessage_Destroy(eventInstance->messageHandle); } -static char msgText[1024]; -#define MESSAGE_COUNT 5 - void iothub_client_sample_mqtt_run(void) { IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle; @@ -90,54 +118,61 @@ void iothub_client_sample_mqtt_run(void) (void)printf("Starting the IoTHub client sample MQTT...\r\n"); - if ((iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, MQTT_Protocol)) == NULL) + if (platform_init() != 0) { - (void)printf("ERROR: iotHubClientHandle is NULL!\r\n"); + (void)printf("ERROR: platform_init fails!\r\n"); } else { - - /* Setting Message call back, so we can receive Commands. */ - if (IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, &receiveContext) != IOTHUB_CLIENT_OK) + if ((iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, MQTT_Protocol)) == NULL) { - (void)printf("ERROR: IoTHubClient_LL_SetMessageCallback..........FAILED!\r\n"); + (void)printf("ERROR: iotHubClientHandle is NULL!\r\n"); } else { - (void)printf("IoTHubClient_LL_SetMessageCallback...successful.\r\n"); - - /* Now that we are ready to receive commands, let's send some messages */ - for (int i = 0; i < MESSAGE_COUNT; i++) + /* Setting Message call back, so we can receive Commands. */ + if (IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, &receiveContext) != IOTHUB_CLIENT_OK) { - sprintf_s(msgText, sizeof(msgText), "{\"deviceId\":\"myFirstDevice\",\"windSpeed\":%.2f}", avgWindSpeed + (rand() % 4 + 2)); - if ((messages[i].messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)msgText, strlen(msgText))) == NULL) - { - (void)printf("ERROR: iotHubMessageHandle is NULL!\r\n"); - } - else - { - messages[i].messageTrackingId = i; + (void)printf("ERROR: IoTHubClient_LL_SetMessageCallback..........FAILED!\r\n"); + } + else + { + (void)printf("IoTHubClient_LL_SetMessageCallback...successful.\r\n"); - if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messages[i].messageHandle, SendConfirmationCallback, &messages[i]) != IOTHUB_CLIENT_OK) + /* Now that we are ready to receive commands, let's send some messages */ + for (size_t i = 0; i < MESSAGE_COUNT; i++) + { + sprintf_s(msgText, sizeof(msgText), "{\"deviceId\":\"myFirstDevice\",\"windSpeed\":%.2f}", avgWindSpeed + (rand() % 4 + 2)); + if ((messages[i].messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)msgText, strlen(msgText))) == NULL) { - (void)printf("ERROR: IoTHubClient_LL_SendEventAsync..........FAILED!\r\n"); + (void)printf("ERROR: iotHubMessageHandle is NULL!\r\n"); } else { - (void)printf("IoTHubClient_LL_SendEventAsync accepted message [%d] for transmission to IoT Hub.\r\n", i); - } + messages[i].messageTrackingId = i; + if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messages[i].messageHandle, SendConfirmationCallback, &messages[i]) != IOTHUB_CLIENT_OK) + { + (void)printf("ERROR: IoTHubClient_LL_SendEventAsync..........FAILED!\r\n"); + } + else + { + (void)printf("IoTHubClient_LL_SendEventAsync accepted message [%d] for transmission to IoT Hub.\r\n", (int)i); + } + + } } } - } - /* Wait for Commands. */ - while (1) - { - IoTHubClient_LL_DoWork(iotHubClientHandle); - ThreadAPI_Sleep(1); - } + /* Wait for Commands. */ + while (1) + { + IoTHubClient_LL_DoWork(iotHubClientHandle); + ThreadAPI_Sleep(1); + } - IoTHubClient_LL_Destroy(iotHubClientHandle); + IoTHubClient_LL_Destroy(iotHubClientHandle); + } + platform_deinit(); } } diff --git a/c/iothub_client/src/iothub_client_ll.c b/c/iothub_client/src/iothub_client_ll.c index e5a2b418..451afe20 100644 --- a/c/iothub_client/src/iothub_client_ll.c +++ b/c/iothub_client/src/iothub_client_ll.c @@ -81,8 +81,9 @@ IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateFromConnectionString(const char* c config->iotHubSuffix = NULL; config->deviceId = NULL; config->deviceKey = NULL; - /* Codes_SRS_IOTHUBCLIENT_LL_04_002: [If it does not, it shall pass the protocolGatewayHostName NULL.] */ - config->protocolGatewayHostName = NULL; + /* Codes_SRS_IOTHUBCLIENT_LL_04_002: [If it does not, it shall pass the protocolGatewayHostName NULL.] */ + config->protocolGatewayHostName = NULL; + config->io_transport_provider_callback = NULL; if ((connString = STRING_construct(connectionString)) == NULL) { @@ -125,7 +126,7 @@ IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateFromConnectionString(const char* c { /* SRS_IOTHUBCLIENT_LL_12_010: [IoTHubClient_LL_CreateFromConnectionString shall fill up the IOTHUB_CLIENT_CONFIG structure using the following mapping: iotHubName = Name, iotHubSuffix = Suffix, deviceId = DeviceId, deviceKey = SharedAccessKey] */ const char* s_token = STRING_c_str(tokenString); - if (strcmp(s_token, HOSTNAME_TOKEN) == 0) + if (strcmp(s_token, HOSTNAME_TOKEN) == 0) { /* SRS_IOTHUBCLIENT_LL_12_009: [IoTHubClient_LL_CreateFromConnectionString shall split the value of HostName to Name and Suffix using the first "." as a separator] */ STRING_TOKENIZER_HANDLE tokenizer2 = NULL; @@ -176,7 +177,7 @@ IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateFromConnectionString(const char* c config->deviceKey = STRING_c_str(deviceKeyString); } } - /* Codes_SRS_IOTHUBCLIENT_LL_04_001: [IoTHubClient_LL_CreateFromConnectionString shall verify the existence of key/value pair GatewayHostName. If it does exist it shall pass the value to IoTHubClient_LL_Create API.] */ + /* Codes_SRS_IOTHUBCLIENT_LL_04_001: [IoTHubClient_LL_CreateFromConnectionString shall verify the existence of key/value pair GatewayHostName. If it does exist it shall pass the value to IoTHubClient_LL_Create API.] */ else if (strcmp(s_token, PROTOCOL_GATEWAY_HOST) == 0) { protocolGateway = STRING_clone(valueString); diff --git a/c/iothub_client/src/iothubtransportmqtt.c b/c/iothub_client/src/iothubtransportmqtt.c index 4b973c64..a605397c 100644 --- a/c/iothub_client/src/iothubtransportmqtt.c +++ b/c/iothub_client/src/iothubtransportmqtt.c @@ -15,255 +15,453 @@ #include "iothub_client_ll.h" #include "iothub_client_private.h" #include "iothubtransportmqtt.h" -#include "mqttapi.h" +#include "mqtt_client.h" +#include "sastoken.h" +#include "tlsio_schannel.h" +#include "tlsio_wolfssl.h" +#include "tlsio_openssl.h" -#define QOS 1 +#include +#include + +#define SAS_TOKEN_DEFAULT_LIFETIME 3600 +#define EPOCH_TIME_T_VALUE 0 +#define DEFAULT_MQTT_KEEPALIVE 20 +#define DEFAULT_PORT_NUMBER 8883 typedef struct MQTTTRANSPORT_HANDLE_DATA_TAG { - STRING_HANDLE hostAddressHandle; - STRING_HANDLE device_id; - STRING_HANDLE device_key; - - STRING_HANDLE sasTokenSr; - - DLIST_ENTRY waitingForAck; - + STRING_HANDLE sasTokenSr; STRING_HANDLE mqttEventTopic; - STRING_HANDLE mqttMessageTopic; - - MQTTAPI_HANDLE mqttApiInstance; - - MQTTAPI_TOPIC_HANDLE messageTopicHandle; - + STRING_HANDLE hostAddress; + // The current mqtt iothub implementation requires that the hub name and the domain suffix be passed as the first of a series of segments + // passed through the username portion of the connection frame. + // The second segment will contain the device id. The two segments are delemited by a "/". + // The first segment can be a maximum 256 characters. + // The second segment can be a maximum 128 characters. + // With the / delimeter you have 384 chars (Plus a terminator of 0). + STRING_HANDLE configPassedThroughUsername; + int portNum; + MQTT_CLIENT_HANDLE mqttClient; + uint16_t packetId; bool connected; - bool subscribed; - + DLIST_ENTRY waitingForAck; PDLIST_ENTRY waitingToSend; - - IOTHUB_CLIENT_LL_HANDLE savedClientHandle; + IOTHUB_CLIENT_LL_HANDLE llClientHandle; + IO_TRANSPORT_PROVIDER_CALLBACK io_transport_provider_callback; + CONTROL_PACKET_TYPE currPacketState; } MQTTTRANSPORT_HANDLE_DATA, *PMQTTTRANSPORT_HANDLE_DATA; typedef struct MQTT_MESSAGE_DETAILS_LIST_TAG { IOTHUB_MESSAGE_LIST* iotHubMessageEntry; void* context; + uint16_t msgPacketId; DLIST_ENTRY entry; -}MQTT_MESSAGE_DETAILS_LIST, *PMQTT_MESSAGE_DETAILS_LIST; +} MQTT_MESSAGE_DETAILS_LIST, *PMQTT_MESSAGE_DETAILS_LIST; -static void delivered(void* context, MQTTAPI_CONFIRMATION_RESULT result) +static void defaultPrintLogFunction(unsigned int options, char* format, ...) { - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_045: [If context is NULL, IoTHubTransportMqtt delivery completed callback shall do nothing.] */ - if (context != NULL) + va_list args; + va_start(args, format); + (void)vprintf(format, args); + va_end(args); + + if (options & LOG_LINE) { - PMQTT_MESSAGE_DETAILS_LIST sentMQTTMessage = context; - PMQTTTRANSPORT_HANDLE_DATA transportState = sentMQTTMessage->context; - - if (transportState != NULL) - { - //First try to find the message on the list. - PDLIST_ENTRY currentListEntry; - currentListEntry = transportState->waitingForAck.Flink; - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_041: [IoTHubTransportMqtt shall search for the message received on context parameter to identify the message.] */ - while (currentListEntry != &transportState->waitingForAck) - { - MQTT_MESSAGE_DETAILS_LIST *mqttMessageDetailEntry = containingRecord(currentListEntry, MQTT_MESSAGE_DETAILS_LIST, entry); - DLIST_ENTRY savedFromCurrentListEntry; - savedFromCurrentListEntry.Flink = currentListEntry->Flink; - - //Identify here if the message is the one arrived. - if (mqttMessageDetailEntry == context) - { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_042: [Once identified, IoTHubTransportMqtt shall remove the message from the WaitingforAck List.] */ - (void)DList_RemoveEntryList(currentListEntry); //First remove the item from Waiting for Ack List. - DLIST_ENTRY messageCompleted; - DList_InitializeListHead(&messageCompleted); - DList_InsertHeadList(&messageCompleted, &(mqttMessageDetailEntry->iotHubMessageEntry->entry)); - - if (result == MQTTAPI_CONFIRMATION_OK) - { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_043: [If result IoTHubTransportMqtt is MQTTAPI_CONFIRMATION_OK IoTHubTransportMqtt shall call IoTHubClient_LL_SendComplete passing the message and status IOTHUB_BATCHSTATE_SUCCESS.] */ - IoTHubClient_LL_SendComplete(transportState->savedClientHandle, &messageCompleted, IOTHUB_BATCHSTATE_SUCCESS); //SendBatchComplete Frees the Message. - } - else - { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_044: [Otherwise, IoTHubTransportMqtt shall call IoTHubClient_LL_SendComplete passing the message and status IOTHUB_BATCHSTATE_FAIL.] */ - IoTHubClient_LL_SendComplete(transportState->savedClientHandle, &messageCompleted, IOTHUB_BATCHSTATE_FAILED); //SendBatchComplete Frees the Message. - } - - break; - } - currentListEntry = savedFromCurrentListEntry.Flink; - } - } - - free(sentMQTTMessage); + (void)printf("\r\n"); } } - -static bool msgarrvd(void* context, const MQTTAPI_Message* message) +static void sendMsgComplete(IOTHUB_MESSAGE_LIST* iothubMsgList, PMQTTTRANSPORT_HANDLE_DATA transportState, IOTHUB_BATCHSTATE_RESULT batchResult) { - int result; + DLIST_ENTRY messageCompleted; + DList_InitializeListHead(&messageCompleted); + DList_InsertTailList(&messageCompleted, &(iothubMsgList->entry)); + IoTHubClient_LL_SendComplete(transportState->llClientHandle, &messageCompleted, batchResult); +} - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_046: [If IoTHubTransportMqtt receives a call to MQTTAPI_messageArrived with message parameter or context NULL, it shall return false] */ - if (context == NULL || message == NULL) +static void MqttRecvCallback(MQTT_MESSAGE_HANDLE msgHandle, void* callbackCtx) +{ + if (msgHandle != NULL && callbackCtx != NULL) { - LogError("Received message, but without any content.\r\n"); - result = false; - } - else - { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_047: [IotHubTransportMqtt shall Create an IoTHubMessage by calling IoTHubMessage_CreateFromByteArray when MQTTAPI_messageArrived is called.] */ - IOTHUB_MESSAGE_HANDLE IoTHubMessage; - - if ((IoTHubMessage = IoTHubMessage_CreateFromByteArray(message->payload, message->payloadlen)) == NULL) + const APP_PAYLOAD* appPayload = mqttmessage_getApplicationMsg(msgHandle); + IOTHUB_MESSAGE_HANDLE IoTHubMessage = IoTHubMessage_CreateFromByteArray(appPayload->message, appPayload->length); + if (IoTHubMessage == NULL) { - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_048: [If the call to IoTHubMessage_CreateFromByteArray fails, IoTHubTransportMqtt message arrived shall return false.] */ - LogError("Failed to Create IoTHubMessage. \r\n"); - result = false; + LogError("IotHub Message creation has failed.\r\n"); } else { - PMQTTTRANSPORT_HANDLE_DATA state = context; - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_051: [IoTHubTransportMqtt shall call IoTHubClient_LL_MessageCallback.] */ - if (IoTHubClient_LL_MessageCallback(state->savedClientHandle, IoTHubMessage) != IOTHUBMESSAGE_ACCEPTED) + PMQTTTRANSPORT_HANDLE_DATA transportData = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx; + if (IoTHubClient_LL_MessageCallback(transportData->llClientHandle, IoTHubMessage) != IOTHUBMESSAGE_ACCEPTED) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_052: [If this calls fails, it shall return false] */ - LogError("Event not accepted by our client. \r\n"); - result = false; + LogError("Event not accepted by our client.\r\n"); } - else - { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_053: [Otherwise it shall return true.] */ - result = true; - } - } - - if (IoTHubMessage != NULL) - { IoTHubMessage_Destroy(IoTHubMessage); } } +} +static void MqttOpCompleteCallback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_RESULT actionResult, const void* msgInfo, void* callbackCtx) +{ + (void)handle; + if (callbackCtx != NULL) + { + PMQTTTRANSPORT_HANDLE_DATA transportData = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx; + switch (actionResult) + { + case MQTT_CLIENT_ON_PUBLISH_ACK: + case MQTT_CLIENT_ON_PUBLISH_COMP: + { + const PUBLISH_ACK* puback = (const PUBLISH_ACK*)msgInfo; + PDLIST_ENTRY currListEntry = transportData->waitingForAck.Flink; + while (currListEntry != &transportData->waitingForAck) + { + MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currListEntry, MQTT_MESSAGE_DETAILS_LIST, entry); + DLIST_ENTRY saveListEntry; + saveListEntry.Flink = currListEntry->Flink; + + if (puback->packetId == mqttMsgEntry->msgPacketId) + { + (void)DList_RemoveEntryList(currListEntry); //First remove the item from Waiting for Ack List. + sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transportData, IOTHUB_BATCHSTATE_SUCCESS); + free(mqttMsgEntry); + } + currListEntry = saveListEntry.Flink; + } + break; + } + case MQTT_CLIENT_ON_CONNACK: + { + const CONNECT_ACK* connack = (const CONNECT_ACK*)msgInfo; + if (connack != NULL) + { + if (connack->returnCode == CONNECTION_ACCEPTED) + { + // The connect packet has been acked + transportData->currPacketState = CONNACK_TYPE; + } + else + { + LogError("Connection not accepted, return code: %d.\r\n", connack->returnCode); + (void)mqtt_client_disconnect(transportData->mqttClient); + transportData->connected = false; + transportData->currPacketState = PACKET_TYPE_ERROR; + } + } + else + { + LogError("MQTT_CLIENT_ON_CONNACK CONNACK parameter is NULL.\r\n"); + } + break; + } + case MQTT_CLIENT_ON_SUBSCRIBE_ACK: + { + const SUBSCRIBE_ACK* suback = (const SUBSCRIBE_ACK*)msgInfo; + if (suback != NULL) + { + if (suback->qosCount == 1) + { + // The connect packet has been acked + transportData->currPacketState = SUBACK_TYPE; + } + else + { + LogError("QOS count was not expected: %d.\r\n", suback->qosCount); + } + } + break; + } + case MQTT_CLIENT_ON_PUBLISH_RECV: + case MQTT_CLIENT_ON_PUBLISH_REL: + { + // Currently not used + break; + } + case MQTT_CLIENT_ON_ERROR: + case MQTT_CLIENT_ON_DISCONNECT: + { + // Close the client so we can reconnect again + (void)mqtt_client_disconnect(transportData->mqttClient); + transportData->connected = false; + transportData->currPacketState = PACKET_TYPE_ERROR; + break; + } + } + } +} + +const XIO_HANDLE defaultIoTransportProvider(const char* fqdn, int port) +{ + const IO_INTERFACE_DESCRIPTION* io_interface_description; + +#ifdef _WIN32 + TLSIO_SCHANNEL_CONFIG tls_io_config = { fqdn, port }; + io_interface_description = tlsio_schannel_get_interface_description(); +#else + #ifdef MBED_BUILD_TIMESTAMP + TLSIO_WOLFSSL_CONFIG tls_io_config = { fqdn, port }; + io_interface_description = tlsio_wolfssl_get_interface_description(); + #else + TLSIO_OPENSSL_CONFIG tls_io_config = { fqdn, port }; + io_interface_description = tlsio_openssl_get_interface_description(); + #endif +#endif + + return (void*)xio_create(io_interface_description, &tls_io_config, NULL/*defaultPrintLogFunction*/); +} + +static int SubscribeToMqttProtocol(PMQTTTRANSPORT_HANDLE_DATA transportState) +{ + int result; + + SUBSCRIBE_PAYLOAD subscribe[] = { + { STRING_c_str(transportState->mqttMessageTopic), DELIVER_AT_LEAST_ONCE } + }; + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_016: [IoTHubTransportMqtt_Subscribe shall call mqtt_client_subscribe to subscribe to the Message Topic.] */ + if (mqtt_client_subscribe(transportState->mqttClient, transportState->packetId++, subscribe, 1) != 0) + { + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_017: [Upon failure IoTHubTransportMqtt_Subscribe shall return a non-zero value.] */ + result = __LINE__; + } + else + { + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_018: [On success IoTHubTransportMqtt_Subscribe shall return 0.] */ + transportState->subscribed = true; + transportState->currPacketState = SUBSCRIBE_TYPE; + result = 0; + } return result; } -static PMQTTTRANSPORT_HANDLE_DATA mqttClientTransportState_Create(STRING_HANDLE hostAddress, const char* iothubName, const char* iotHubSuffix, const char* deviceId, const char* deviceKey, PDLIST_ENTRY waitingToSend) +static const unsigned char* RetrieveMessagePayload(IOTHUB_MESSAGE_HANDLE messageHandle, size_t* length) { - PMQTTTRANSPORT_HANDLE_DATA state; - state = (PMQTTTRANSPORT_HANDLE_DATA)malloc(sizeof(MQTTTRANSPORT_HANDLE_DATA)); + const unsigned char* result; + + IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(messageHandle); + if (contentType == IOTHUBMESSAGE_BYTEARRAY) + { + if (IoTHubMessage_GetByteArray(messageHandle, &result, length) != IOTHUB_MESSAGE_OK) + { + LogError("Failure result from IoTHubMessage_GetByteArray\r\n"); + result = NULL; + *length = 0; + } + } + else if (contentType == IOTHUBMESSAGE_STRING) + { + result = (const unsigned char*)IoTHubMessage_GetString(messageHandle); + if (result == NULL) + { + LogError("Failure result from IoTHubMessage_GetString\r\n"); + result = NULL; + *length = 0; + } + else + { + *length = strlen((const char*)result); + } + } + else + { + result = NULL; + *length = 0; + } + return result; +} + +static STRING_HANDLE ConstructSasToken(const char* iothubName, const char* iotHubSuffix, const char* deviceId) +{ + STRING_HANDLE result; + size_t len = strlen(iothubName); + len += strlen(iotHubSuffix); + len += strlen(deviceId); + + char* sasToken = malloc(len + 10 + 1); + if (sasToken == NULL) + { + result = NULL; + } + else + { + (void)sprintf(sasToken, "%s.%s/devices/%s", iothubName, iotHubSuffix, deviceId); + result = STRING_construct(sasToken); + free(sasToken); + } + return result; +} + +static STRING_HANDLE ConstructEventTopic(const char* deviceId) +{ + STRING_HANDLE result; + size_t len = strlen(deviceId); + + char* eventTopic = malloc(len + 24 + 1); + if (eventTopic == NULL) + { + result = NULL; + } + else + { + (void)sprintf(eventTopic, "devices/%s/messages/events", deviceId); + result = STRING_construct(eventTopic); + free(eventTopic); + } + return result; +} + +static STRING_HANDLE ConstructMessageTopic(const char* deviceId) +{ + STRING_HANDLE result; + size_t len = strlen(deviceId); + + char* messageTopic = malloc(len + 29 + 1); + if (messageTopic == NULL) + { + result = NULL; + } + else + { + (void)sprintf(messageTopic, "devices/%s/messages/devicebound", deviceId); + result = STRING_construct(messageTopic); + free(messageTopic); + } + return result; +} + +static int InitializeConnection(PMQTTTRANSPORT_HANDLE_DATA transportState, bool initialConnection) +{ + int result = 0; + if (!transportState->connected) + { + // Construct SAS token + size_t secSinceEpoch = (size_t)(difftime(get_time(NULL), EPOCH_TIME_T_VALUE) + 0); + size_t expiryTime = secSinceEpoch + SAS_TOKEN_DEFAULT_LIFETIME; + + // Not checking the success of this variable, if fail it will fail in the SASToken creation and return false; + STRING_HANDLE emptyKeyName = STRING_new(); + STRING_HANDLE sasToken = SASToken_Create(transportState->device_key, transportState->sasTokenSr, emptyKeyName, expiryTime); + if (sasToken == NULL) + { + result = __LINE__; + } + else + { + MQTT_CLIENT_OPTIONS options = { 0 }; + options.clientId = (char*)STRING_c_str(transportState->device_id); + options.willMessage = NULL; + options.username = (char*)STRING_c_str(transportState->configPassedThroughUsername); + options.password = (char*)STRING_c_str(sasToken); + options.keepAliveInterval = DEFAULT_MQTT_KEEPALIVE; + options.useCleanSession = false;// initialConnection; + options.qualityOfServiceValue = DELIVER_AT_LEAST_ONCE; + + // construct address + const char* hostAddress = STRING_c_str(transportState->hostAddress); + const char* hostName = strstr(hostAddress, "//"); + if (hostName == NULL) + { + hostName = hostAddress; + } + else + { + // Increment beyond the double backslash + hostName += 2; + } + XIO_HANDLE xio = transportState->io_transport_provider_callback(hostName, transportState->portNum); + if (mqtt_client_connect(transportState->mqttClient, xio, &options) != 0) + { + LogError("failure connecting to address %s:%d.\r\n", STRING_c_str(transportState->hostAddress), transportState->portNum); + result = __LINE__; + } + else + { + transportState->connected = true; + result = 0; + } + STRING_delete(emptyKeyName); + STRING_delete(sasToken); + } + } + return result; +} + +static STRING_HANDLE buildConfigForUsername(const IOTHUB_CLIENT_CONFIG* upperConfig) +{ + STRING_HANDLE result; + if (((result = STRING_construct(upperConfig->iotHubName)) == NULL) || + (STRING_concat(result,".") != 0) || + (STRING_concat(result,upperConfig->iotHubSuffix) != 0) || + (STRING_concat(result, "/") != 0) || + (STRING_concat(result, upperConfig->deviceId) != 0)) + { + STRING_delete(result); + result = NULL; + } + return result; +} + +static PMQTTTRANSPORT_HANDLE_DATA InitializeTransportHandleData(const IOTHUB_CLIENT_CONFIG* upperConfig, PDLIST_ENTRY waitingToSend) +{ + PMQTTTRANSPORT_HANDLE_DATA state = (PMQTTTRANSPORT_HANDLE_DATA)malloc(sizeof(MQTTTRANSPORT_HANDLE_DATA)); if (state == NULL) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_010: [If memory allocation fails IoTHubTransportMqtt_Create shall fail and return NULL.] */ LogError("Could not create MQTT transport state. Memory allocation failed.\r\n"); } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_009: [IoTHubTransportMqtt_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key, sasTokenSr and client handle shall be saved.] */ - else if ((state->device_id = STRING_construct(deviceId)) == NULL) + else if ((state->device_id = STRING_construct(upperConfig->deviceId)) == NULL) { - LogError("Could not create device id for MQTT\r\n"); free(state); state = NULL; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_009: [IoTHubTransportMqtt_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key, sasTokenSr and client handle shall be saved.] */ - else if ((state->device_key = STRING_construct(deviceKey)) == NULL) + else if ((state->device_key = STRING_construct(upperConfig->deviceKey)) == NULL) { LogError("Could not create device key for MQTT\r\n"); STRING_delete(state->device_id); free(state); state = NULL; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_009: [IoTHubTransportMqtt_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key, sasTokenSr and client handle shall be saved.] */ - else if ((state->sasTokenSr = STRING_construct(iothubName)) == NULL || - (STRING_concat(state->sasTokenSr, ".")) != 0 || - (STRING_concat(state->sasTokenSr, iotHubSuffix)) != 0 || - (STRING_concat(state->sasTokenSr, "/devices/")) != 0 || - (STRING_concat(state->sasTokenSr, deviceId)) != 0) - { - LogError("Could not create Sas Token Sr String.\r\n"); - STRING_delete(state->sasTokenSr); - STRING_delete(state->device_key); - STRING_delete(state->device_id); - free(state); - state = NULL; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_005: [Otherwise, IoTHubTransportMqtt_Create shall create an immutable string (further called Event mqttEventTopic) that will be formed by devices//messages/events.] */ - else if ((state->mqttEventTopic = STRING_construct("devices/")) == NULL || - (STRING_concat(state->mqttEventTopic, deviceId)) != 0 || - (STRING_concat(state->mqttEventTopic, "/messages/events")) != 0) + else if ( (state->sasTokenSr = ConstructSasToken(upperConfig->iotHubName, upperConfig->iotHubSuffix, upperConfig->deviceId) ) == NULL) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_006: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ - LogError("Could not create mqttEventTopic for MQTT\r\n"); - STRING_delete(state->sasTokenSr); + LogError("Could not create Sas Token Sr String.\r\n"); STRING_delete(state->device_key); STRING_delete(state->device_id); - STRING_delete(state->mqttEventTopic); free(state); state = NULL; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_007: [Otherwise, IoTHubTransportMqtt_Create shall create an immutable string(further called Event mqttMessageTopic) that will be formed by devices//messages/devicebound.] */ - else if ((state->mqttMessageTopic = STRING_construct("devices/")) == NULL|| - (STRING_concat(state->mqttMessageTopic, deviceId)) != 0 || - (STRING_concat(state->mqttMessageTopic, "/messages/devicebound")) != 0) + else if ( (state->mqttEventTopic = ConstructEventTopic(upperConfig->deviceId) ) == NULL) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_008: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ - LogError("Could not create mqttMessageTopic for MQTT\r\n"); - STRING_delete(state->mqttEventTopic); - STRING_delete(state->sasTokenSr); + LogError("Could not create mqttEventTopic for MQTT\r\n"); + STRING_delete(state->sasTokenSr); + STRING_delete(state->device_key); + STRING_delete(state->device_id); + free(state); + state = NULL; + } + else if ((state->mqttMessageTopic = ConstructMessageTopic(upperConfig->deviceId) ) == NULL) + { + LogError("Could not create mqttMessageTopic for MQTT\r\n"); + STRING_delete(state->mqttEventTopic); + STRING_delete(state->sasTokenSr); STRING_delete(state->device_key); STRING_delete(state->device_id); - STRING_delete(state->mqttMessageTopic); free(state); state = NULL; } else { - /* CodesSRS_IOTHUBTRANSPORTMQTT_04_011: [IoTHubTransportMqtt_Create shall call MQTTAPI_Create passing MQTTAPI_connectOptions (deviceId, deviceKey and HostAddress).] */ - MQTTAPI_ConnectOptions connOpt; - connOpt.deviceId = STRING_c_str(state->device_id); - connOpt.deviceKey = STRING_c_str(state->device_key); - connOpt.serverURI = STRING_c_str(hostAddress); - connOpt.sasTokenSr = STRING_c_str(state->sasTokenSr); - - if ((state->mqttApiInstance = MQTTAPI_Create(&connOpt)) == NULL) + state->mqttClient = mqtt_client_init(MqttRecvCallback, MqttOpCompleteCallback, state, defaultPrintLogFunction); + if (state->mqttClient == NULL) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_012: [If MQTTAPI_Create fail, than IoTHubTransportMqtt_Create shall fail and return NULL.] */ - LogError("Could not create MQTTAPI instance.\r\n"); STRING_delete(state->mqttEventTopic); STRING_delete(state->mqttMessageTopic); - STRING_delete(state->sasTokenSr); - STRING_delete(state->device_key); - STRING_delete(state->device_id); - free(state); - state = NULL; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_025: [IoTHubTransportMqtt_Create shall call MQTTAPI_SetMessageCallback and MQTTAPI_SetDeliveryCompletedCallback for message arrived and message delivered (Answer to Event).] */ - else if (MQTTAPI_SetMessageCallback(state->mqttApiInstance, state, msgarrvd) != MQTTAPI_OK) - { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_026: [If MQTTAPI_SetCallbaks fails, IoTHubTransportMqtt_Create shall fail and return NULL.] */ - LogError("Could not set message callback.\r\n"); - STRING_delete(state->mqttEventTopic); - STRING_delete(state->mqttMessageTopic); - STRING_delete(state->sasTokenSr); - STRING_delete(state->device_key); - STRING_delete(state->device_id); - free(state); - state = NULL; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_025: [IoTHubTransportMqtt_Create shall call MQTTAPI_SetMessageCallback and MQTTAPI_SetDeliveryCompletedCallback for message arrived and message delivered (Answer to Event).] */ - else if (MQTTAPI_SetDeliveryCompletedCallback(state->mqttApiInstance, delivered) != MQTTAPI_OK) - { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_026: [If MQTTAPI_SetCallbaks fails, IoTHubTransportMqtt_Create shall fail and return NULL.] */ - LogError("Could not set event confirmation callback.\r\n"); - STRING_delete(state->mqttEventTopic); - STRING_delete(state->mqttMessageTopic); - STRING_delete(state->sasTokenSr); + STRING_delete(state->sasTokenSr); STRING_delete(state->device_key); STRING_delete(state->device_id); free(state); @@ -271,286 +469,274 @@ static PMQTTTRANSPORT_HANDLE_DATA mqttClientTransportState_Create(STRING_HANDLE } else { - state->hostAddressHandle = hostAddress; - state->connected = false; - state->subscribed = false; - state->waitingToSend = waitingToSend; - state->savedClientHandle = NULL; - state->messageTopicHandle = NULL; - DList_InitializeListHead(&(state->waitingForAck)); + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_008: [If the upperConfig contains a valid protocolGatewayHostName value the this shall be used for the hostname, otherwise the hostname shall be constructed using the iothubname and iothubSuffix.] */ + // TODO: need to strip the ssl or http or tls + char tempAddress[256]; + if (upperConfig->protocolGatewayHostName) + { + (void)snprintf(tempAddress, 256, "%s", upperConfig->protocolGatewayHostName); + } + else + { + (void)snprintf(tempAddress, 256, "%s.%s", upperConfig->iotHubName, upperConfig->iotHubSuffix); + } + if ((state->hostAddress = STRING_construct(tempAddress)) == NULL) + { + STRING_delete(state->mqttEventTopic); + STRING_delete(state->mqttMessageTopic); + STRING_delete(state->sasTokenSr); + STRING_delete(state->device_key); + STRING_delete(state->device_id); + free(state); + state = NULL; + } + else if ((state->configPassedThroughUsername = buildConfigForUsername(upperConfig)) == NULL) + { + STRING_delete(state->hostAddress); + STRING_delete(state->mqttEventTopic); + STRING_delete(state->mqttMessageTopic); + STRING_delete(state->sasTokenSr); + STRING_delete(state->device_key); + STRING_delete(state->device_id); + free(state); + state = NULL; + + } + else + { + if (upperConfig->io_transport_provider_callback != NULL) + { + state->io_transport_provider_callback = upperConfig->io_transport_provider_callback; + } + else + { + state->io_transport_provider_callback = defaultIoTransportProvider; + } + + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_010: [IoTHubTransportMqtt_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key, sasTokenSr and client handle shall be saved.] */ + DList_InitializeListHead(&(state->waitingForAck)); + state->subscribed = false; + state->connected = false; + state->packetId = 1; + state->llClientHandle = NULL; + state->portNum = DEFAULT_PORT_NUMBER; + state->waitingToSend = waitingToSend; + state->currPacketState = CONNECT_TYPE; + } } } - return state; } - - extern TRANSPORT_HANDLE IoTHubTransportMqtt_Create(const IOTHUBTRANSPORT_CONFIG* config) { - PMQTTTRANSPORT_HANDLE_DATA result; size_t deviceIdSize; - STRING_HANDLE hostAddress; - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_001: [If parameter config is NULL then IoTHubTransportMqtt_Create shall fail and return NULL.] */ + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_001: [If parameter config is NULL then IoTHubTransportMqtt_Create shall return NULL.] */ if (config == NULL) { - LogError("Config Parameter is NULL.\r\n"); + LogError("Invalid Argument: Config Parameter is NULL.\r\n"); result = NULL; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ - else if (config->upperConfig == NULL) + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [If the parameter config's variables upperConfig or waitingToSend are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ + else if (config->upperConfig == NULL || config->upperConfig->protocol == NULL || config->upperConfig->deviceId == NULL || config->upperConfig->deviceKey == NULL || + config->upperConfig->iotHubName == NULL || config->upperConfig->iotHubSuffix == NULL) { - LogError("invalid arg (upperConfig is NULL)\r\n"); + LogError("Invalid Argument: upperConfig structure contains an invalid parameter\r\n"); result = NULL; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [If the parameter config's variables upperConfig or waitingToSend are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ else if (config->waitingToSend == NULL) { - LogError("invalid arg (waitingToSend is NULL)\r\n"); + LogError("Invalid Argument: waitingToSend is NULL)\r\n"); result = NULL; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ - else if (config->upperConfig->protocol == NULL) + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_006: [If the upperConfig's variables deviceId is an empty strings or length is greater then 128 then IoTHubTransportMqtt_Create shall return NULL.] */ + else if ( ( (deviceIdSize = strlen(config->upperConfig->deviceId)) > 128U) || (deviceIdSize == 0) ) { - LogError("invalid arg (protocol is NULL)\r\n"); + LogError("Invalid Argument: DeviceId is of an invalid size\r\n"); result = NULL; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ - else if (config->upperConfig->deviceId == NULL) - { - LogError("invalid arg (deviceId is NULL)\r\n"); - result = NULL; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ - else if (config->upperConfig->deviceKey == NULL) - { - LogError("invalid arg (deviceKey is NULL)\r\n"); - result = NULL; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ - else if (config->upperConfig->iotHubName == NULL) - { - LogError("invalid arg (iotHubName is NULL)\r\n"); - result = NULL; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ - else if (config->upperConfig->iotHubSuffix == NULL) - { - LogError("invalid arg (iotHubSuffix is NULL)\r\n"); - result = NULL; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ - else if (config->upperConfig->protocolGatewayHostName == NULL) - { - LogError("invalid arg (protocolGatewayHostName is NULL)\r\n"); - result = NULL; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_003: [IoTHubTransportMqtt_Create shall fail and return NULL if the configuration deviceId is greater than 128 ascii characters.] */ - else if ((deviceIdSize = strlen(config->upperConfig->deviceId)) > 128U) - { - LogError("invalid arg (device Id is longer than 128 ASCII Characters)\r\n"); - result = NULL; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_004: [IoTHubTransportMqtt_Create shall fail and return NULL if the configuration parameters deviceId, deviceKey, IoTHubName and protocolGatewayHostName are an empty string in size.] */ - else if ((deviceIdSize == 0)) - { - LogError("invalid arg (device Id is empty)\r\n"); - result = NULL; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_004: [IoTHubTransportMqtt_Create shall fail and return NULL if the configuration parameters deviceId, deviceKey, IoTHubName and protocolGatewayHostName are an empty string in size.] */ + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ else if (strlen(config->upperConfig->deviceKey) == 0) { - LogError("invalid arg (device key is empty)\r\n"); + LogError("Invalid Argument: deviceKey is empty\r\n"); result = NULL; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_004: [IoTHubTransportMqtt_Create shall fail and return NULL if the configuration parameters deviceId, deviceKey, IoTHubName and protocolGatewayHostName are an empty string in size.] */ + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ else if (strlen(config->upperConfig->iotHubName) == 0) { - LogError("invalid arg (iotHubName is empty)\r\n"); + LogError("Invalid Argument: iotHubName is empty\r\n"); result = NULL; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_004: [IoTHubTransportMqtt_Create shall fail and return NULL if the configuration parameters deviceId, deviceKey, IoTHubName and protocolGatewayHostName are an empty string in size.] */ - else if (strlen(config->upperConfig->protocolGatewayHostName) == 0) + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_007: [If the upperConfig's variables protocolGatewayHostName is non-Null and the length is an empty string then IoTHubTransportMqtt_Create shall return NULL.] */ + else if (config->upperConfig->protocolGatewayHostName != NULL && strlen(config->upperConfig->protocolGatewayHostName) == 0) { - LogError("invalid arg (protocolGatewayHostName is empty)\r\n"); + LogError("Invalid Argument: protocolGatewayHostName is an empty string\r\n"); result = NULL; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_009: [IoTHubTransportMqtt_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key and client handle shall be saved.] */ - else if ((hostAddress = STRING_construct(config->upperConfig->protocolGatewayHostName)) == NULL) + else { - LogError("Failed to construct MQTT address for Event.\r\n"); - result = NULL; + result = InitializeTransportHandleData(config->upperConfig, config->waitingToSend); } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_013: [Otherwise, IoTHubTransportMqtt_Create shall succeed and return a non-NULL value] */ - else if ((result = mqttClientTransportState_Create(hostAddress, config->upperConfig->iotHubName, config->upperConfig->iotHubSuffix, config->upperConfig->deviceId, config->upperConfig->deviceKey, config->waitingToSend)) == NULL) - { - STRING_delete(hostAddress); - LogError("Failed to allocate the state for the mqtt transport\r\n"); - } - + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_009: [If any error is encountered then IoTHubTransportMqtt_Create shall return NULL.] */ + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_011: [On Success IoTHubTransportMqtt_Create shall return a non-NULL value.] */ return result; } -extern void IoTHubTransportMqtt_Destroy(TRANSPORT_HANDLE handle) +void IoTHubTransportMqtt_Destroy(TRANSPORT_HANDLE handle) { + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_012: [IoTHubTransportMqtt_Destroy shall do nothing if parameter handle is NULL.] */ PMQTTTRANSPORT_HANDLE_DATA transportState = (PMQTTTRANSPORT_HANDLE_DATA)handle; - - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_014: [IoTHubTransportMqtt_Destroy shall do nothing if parameter handle is NULL.] */ if (transportState != NULL) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_015: [Otherwise IoTHubTransportMqtt_Destroy shall free all the resources currently in use.] */ + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_013: [If the parameter subscribe is true then IoTHubTransportMqtt_Destroy shall call IoTHubTransportMqtt_Unsubscribe.] */ if (transportState->subscribed) { IoTHubTransportMqtt_Unsubscribe(handle); } + //Empty the Waiting for Ack Messages. while (!DList_IsListEmpty(&transportState->waitingForAck)) { - DLIST_ENTRY messageCompleted; PDLIST_ENTRY currentEntry = DList_RemoveHeadList(&transportState->waitingForAck); - - MQTT_MESSAGE_DETAILS_LIST* mqttMessageEntry = containingRecord(currentEntry, MQTT_MESSAGE_DETAILS_LIST, entry); - - DList_InitializeListHead(&messageCompleted); - DList_InsertTailList(&messageCompleted, &(mqttMessageEntry->iotHubMessageEntry->entry)); - IoTHubClient_LL_SendComplete(transportState->savedClientHandle, &messageCompleted, IOTHUB_BATCHSTATE_FAILED); - free(mqttMessageEntry); + MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currentEntry, MQTT_MESSAGE_DETAILS_LIST, entry); + sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transportState, IOTHUB_BATCHSTATE_FAILED); + free(mqttMsgEntry); } + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_014: [IoTHubTransportMqtt_Destroy shall free all the resources currently in use.] */ + (void)mqtt_client_disconnect(transportState->mqttClient); + transportState->connected = false; + transportState->currPacketState = DISCONNECT_TYPE; + mqtt_client_deinit(transportState->mqttClient); STRING_delete(transportState->mqttEventTopic); STRING_delete(transportState->mqttMessageTopic); STRING_delete(transportState->device_id); STRING_delete(transportState->device_key); - STRING_delete(transportState->hostAddressHandle); - STRING_delete(transportState->sasTokenSr); - - MQTTAPI_Destroy(transportState->mqttApiInstance); + STRING_delete(transportState->sasTokenSr); + STRING_delete(transportState->hostAddress); + STRING_delete(transportState->configPassedThroughUsername); free(transportState); } } -extern int IoTHubTransportMqtt_Subscribe(TRANSPORT_HANDLE handle) +int IoTHubTransportMqtt_Subscribe(TRANSPORT_HANDLE handle) { int result; PMQTTTRANSPORT_HANDLE_DATA transportState = (PMQTTTRANSPORT_HANDLE_DATA)handle; - if (transportState == NULL) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_016: [If parameter handle is NULL than IoTHubTransportMqtt_Subscribe shall fail and return a non-zero value.] */ + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_015: [If parameter handle is NULL than IoTHubTransportMqtt_Subscribe shall return a non-zero value.] */ LogError("Invalid handle parameter. NULL.\r\n"); result = __LINE__; } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_017: [Otherwise, IoTHubTransportMqtt_Subscribe shall call MQTTAPI_Subscribe.] */ - else if ((transportState->messageTopicHandle = MQTTAPI_Subscribe(transportState->mqttApiInstance, STRING_c_str(transportState->mqttMessageTopic))) == NULL) - { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_019: [Otherwise, IoTHubTransportMqtt_Subscribe shall fail and return a non-zero value.] */ - LogError("MATTAPI_subscribe failed.\r\n"); - result = __LINE__; - } else { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_018: [If MQTTAPI_Subscribe succeeed, IoTHubTransportMqtt_Subscribe shall succeed.] */ - transportState->subscribed = true; result = 0; } - - return result; } -extern void IoTHubTransportMqtt_Unsubscribe(TRANSPORT_HANDLE handle) +void IoTHubTransportMqtt_Unsubscribe(TRANSPORT_HANDLE handle) { PMQTTTRANSPORT_HANDLE_DATA transportState = (PMQTTTRANSPORT_HANDLE_DATA)handle; - - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_020: [If parameter handle is NULL then IoTHubTransportMqtt_Unsubscribe shall do nothing.] */ - if (transportState != NULL) + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_019: [If parameter handle is NULL then IoTHubTransportMqtt_Unsubscribe shall do nothing.] */ + if (transportState != NULL && transportState->subscribed) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_021: [Otherwise it shall call MQTTAPI_Unsubscribe.] */ - MQTTAPI_Unsubscribe(transportState->messageTopicHandle); + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_020: [IoTHubTransportMqtt_Unsubscribe shall call mqtt_client_unsubscribe to unsubscribe the mqtt message topic.] */ + const char* unsubscribe[] = { STRING_c_str(transportState->mqttMessageTopic) }; + (void)mqtt_client_unsubscribe(transportState->mqttClient, transportState->packetId++, unsubscribe, 1); transportState->subscribed = false; } } extern void IoTHubTransportMqtt_DoWork(TRANSPORT_HANDLE handle, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle) { + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_026: [IoTHubTransportMqtt_DoWork shall do nothing if parameter handle and/or iotHubClientHandle is NULL.] */ PMQTTTRANSPORT_HANDLE_DATA transportState = (PMQTTTRANSPORT_HANDLE_DATA)handle; - - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_022: [If parameter handle is NULL or parameter iotHubClientHandle then IoTHubTransportMqtt_DoWork shall immediately return.] */ if (transportState != NULL && iotHubClientHandle != NULL) { - transportState->savedClientHandle = iotHubClientHandle; - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_027: [IoTHubTransportMqtt_DoWork shall inspect the waitingToSend DLIST passed in config structure.] */ - PDLIST_ENTRY currentListEntry; - currentListEntry = transportState->waitingToSend->Flink; + transportState->llClientHandle = iotHubClientHandle; - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_028: [If the list is empty then IoTHubTransportMqtt_DoWork shall proceed to the following action.] */ - while (currentListEntry != transportState->waitingToSend) + if (InitializeConnection(transportState, true) != 0) { - IOTHUB_MESSAGE_LIST *iotHubMessageEntry = containingRecord(currentListEntry, IOTHUB_MESSAGE_LIST, entry); - DLIST_ENTRY savedFromCurrentListEntry; - const unsigned char* messagePayload; - size_t messageLength; - IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(iotHubMessageEntry->messageHandle); - - savedFromCurrentListEntry.Flink = currentListEntry->Flink; - - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_031: [If the list has at least one entry IotHubTransportMQtt_DoWork shall call IotHubMessage_GetData to receive message content and size.]*/ - /*Codes_SRS_IOTHUBTRANSPORTMQTT_02_001: [If the message type is IOTHUBMESSAGE_STRING then IotHubTransportMQtt_DoWork shall call IotHubMessage_GetString to receive message content and shall compute the size as strlen.] */ - if (!( - ((contentType == IOTHUBMESSAGE_BYTEARRAY) && (IoTHubMessage_GetByteArray(iotHubMessageEntry->messageHandle, &messagePayload, &messageLength) == IOTHUB_MESSAGE_OK)) || - ((contentType == IOTHUBMESSAGE_STRING) && ( - messagePayload = (const unsigned char*)IoTHubMessage_GetString(iotHubMessageEntry->messageHandle), - (messageLength = (messagePayload == NULL) ? 0 : strlen((const char*)messagePayload)), - messagePayload != NULL) - ) - )) + // Don't want to flood the logs with failures here + } + else + { + if (transportState->currPacketState == CONNACK_TYPE) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_032: [If IoTHubMessage_GetDatafail, IoTHubTransportMqtt_DoWork shall go to the next item on the list or move to the next action.] */ - LogError("Failure result from IoTHubMessage_GetData\r\n"); + (void)SubscribeToMqttProtocol(transportState); } - else + else if (transportState->currPacketState == SUBACK_TYPE) { - MQTT_MESSAGE_DETAILS_LIST *mqttMessageEntry = (MQTT_MESSAGE_DETAILS_LIST *)malloc(sizeof(MQTT_MESSAGE_DETAILS_LIST)); - - if (mqttMessageEntry == NULL) + // Publish can be called now + transportState->currPacketState = PUBLISH_TYPE; + } + else if (transportState->currPacketState == PUBLISH_TYPE) + { + PDLIST_ENTRY currentListEntry; + currentListEntry = transportState->waitingToSend->Flink; + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransportMqtt_DoWork shall inspect the waitingToSend DLIST passed in config structure.] */ + while (currentListEntry != transportState->waitingToSend) { - LogError("Failed to create a MQTT Detail List Entry. \r\n."); - } - else - { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_033: [Otherwise IoTHubTransportMqtt_DoWork shall call MQTTAPI_PublishMessage, passing the address of the message as a context parameter.] */ - MQTTAPI_Message pubmsg; - pubmsg.payload = (void*)messagePayload; - pubmsg.payloadlen = messageLength; - mqttMessageEntry->iotHubMessageEntry = iotHubMessageEntry; - mqttMessageEntry->context = transportState; + IOTHUB_MESSAGE_LIST* iothubMsgList = containingRecord(currentListEntry, IOTHUB_MESSAGE_LIST, entry); + DLIST_ENTRY savedFromCurrentListEntry; + savedFromCurrentListEntry.Flink = currentListEntry->Flink; - (void)(DList_RemoveEntryList(currentListEntry)); - - if (MQTTAPI_PublishMessage(transportState->mqttApiInstance, STRING_c_str(transportState->mqttEventTopic), &pubmsg, mqttMessageEntry) != MQTTAPI_OK) + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransportMqtt_DoWork shall inspect the waitingToSend DLIST passed in config structure.] */ + size_t messageLength; + const unsigned char* messagePayload = RetrieveMessagePayload(iothubMsgList->messageHandle, &messageLength); + if (messageLength == 0 || messagePayload == NULL) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_034: [If MQTTAPI_PublishMessage fails, IoTHubTransportMqtt_DoWork shall call IoTHubClient_LL_SendComplete with status of IOTHUB_BATCHSTATE_FAILED.] */ - DLIST_ENTRY messageCompleted; - DList_InitializeListHead(&messageCompleted); - DList_InsertTailList(&messageCompleted, &(mqttMessageEntry->iotHubMessageEntry->entry)); - IoTHubClient_LL_SendComplete(transportState->savedClientHandle, &messageCompleted, IOTHUB_BATCHSTATE_FAILED); //SendBatchComplete Frees the Message. - free(mqttMessageEntry); + LogError("Failure result from IoTHubMessage_GetData\r\n"); } else { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_030: [Otherwise the message shall be removed from waitingToSend and moved to a list where it will be waiting for receiving an ACK from Mqtt server(IoTHub or ProtocolGateway)] */ - DList_InsertTailList(&(transportState->waitingForAck), &(mqttMessageEntry->entry)); + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_029: [IoTHubTransportMqtt_DoWork shall create a MQTT_MESSAGE_HANDLE and pass this to a call to mqtt_client_publish.] */ + MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = (MQTT_MESSAGE_DETAILS_LIST*)malloc(sizeof(MQTT_MESSAGE_DETAILS_LIST)); + if (mqttMsgEntry == NULL) + { + LogError("Allocation Error: Failure allocating MQTT Message Detail List.\r\n"); + } + else + { + mqttMsgEntry->msgPacketId = transportState->packetId; + mqttMsgEntry->iotHubMessageEntry = iothubMsgList; + MQTT_MESSAGE_HANDLE mqttMsg = mqttmessage_create(transportState->packetId++, STRING_c_str(transportState->mqttEventTopic), DELIVER_AT_LEAST_ONCE, messagePayload, messageLength); + if (mqttMsg == NULL) + { + sendMsgComplete(iothubMsgList, transportState, IOTHUB_BATCHSTATE_FAILED); + free(mqttMsgEntry); + } + else + { + (void)(DList_RemoveEntryList(currentListEntry)); + + if (mqtt_client_publish(transportState->mqttClient, mqttMsg) != 0) + { + DLIST_ENTRY messageCompleted; + DList_InitializeListHead(&messageCompleted); + DList_InsertTailList(&messageCompleted, &(iothubMsgList->entry)); + IoTHubClient_LL_SendComplete(transportState->llClientHandle, &messageCompleted, IOTHUB_BATCHSTATE_FAILED); + free(mqttMsgEntry); + } + else + { + DList_InsertTailList(&(transportState->waitingForAck), &(mqttMsgEntry->entry)); + } + } + } } + currentListEntry = savedFromCurrentListEntry.Flink; } } - - currentListEntry = savedFromCurrentListEntry.Flink; + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_030: [IoTHubTransportMqtt_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.] */ + mqtt_client_dowork(transportState->mqttClient); } - - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_040: [IoTHubTransportMqtt_DoWork shall call MQTTAPI_DoWork everytime it is called, once.] */ - MQTTAPI_DoWork(transportState->mqttApiInstance); } } @@ -558,16 +744,10 @@ IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_GetSendStatus(TRANSPORT_HANDLE handle, { IOTHUB_CLIENT_RESULT result; - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_035: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */ - if (handle == NULL) + if (handle == NULL || iotHubClientStatus == NULL) { - LogError("invalid arument. handle is NULL. \r\n"); - result = IOTHUB_CLIENT_INVALID_ARG; - } - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_035: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */ - else if (iotHubClientStatus == NULL) - { - LogError("invalid arument. iotHubClientStatus is NULL. \r\n"); + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_023: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */ + LogError("invalid arument. \r\n"); result = IOTHUB_CLIENT_INVALID_ARG; } else @@ -575,34 +755,67 @@ IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_GetSendStatus(TRANSPORT_HANDLE handle, MQTTTRANSPORT_HANDLE_DATA* handleData = (MQTTTRANSPORT_HANDLE_DATA*)handle; if (!DList_IsListEmpty(handleData->waitingToSend) || !DList_IsListEmpty(&(handleData->waitingForAck))) { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_037: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.] */ + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_025: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.] */ *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_BUSY; } else { - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_036: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.] */ + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_024: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.] */ *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_IDLE; } - result = IOTHUB_CLIENT_OK; } - return result; } IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_SetOption(TRANSPORT_HANDLE handle, const char* option, const void* value) { - (void)(handle, option, value); - /* Codes_SRS_IOTHUBTRANSPORTMQTT_04_038: [IoTHubTransportMqtt_SetOption shall return IOTHUB_CLIENT_ERROR , since it does not support any extra parameter today.] */ - return IOTHUB_CLIENT_ERROR; + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_021: [If any parameter is NULL then IoTHubTransportMqtt_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */ + IOTHUB_CLIENT_RESULT result; + if ( + (handle == NULL) || + (option == NULL) || + (value == NULL) + ) + { + result = IOTHUB_CLIENT_INVALID_ARG; + LogError("invalid parameter (NULL) passed to clientTransportAMQP_SetOption\r\n"); + } + else + { + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_031: [If the option parameter is set to "logtrace" then the value shall be a bool_ptr and the value will determine if the mqtt client log is on or off.] */ + if (strcmp("logtrace", option) == 0) + { + MQTTTRANSPORT_HANDLE_DATA* transportState = (MQTTTRANSPORT_HANDLE_DATA*)handle; + bool* traceVal = (bool*)value; + mqtt_client_set_trace(transportState->mqttClient, *traceVal); + result = IOTHUB_CLIENT_OK; + } + else + { + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_032: [IoTHubTransportMqtt_SetOption shall return IOTHUB_CLIENT_INVALID_ARG if the option parameter is not a known option string*] */ + result = IOTHUB_CLIENT_INVALID_ARG; + } + } + return result; } -/* Codes_SRS_IOTHUBTRANSPORTMQTT_04_039: [This function shall return a pointer to a structure of type TRANSPORT_PROVIDER having the following values for its fields:] */ TRANSPORT_PROVIDER myfunc = { IoTHubTransportMqtt_SetOption, - IoTHubTransportMqtt_Create, IoTHubTransportMqtt_Destroy, IoTHubTransportMqtt_Subscribe, IoTHubTransportMqtt_Unsubscribe, IoTHubTransportMqtt_DoWork, IoTHubTransportMqtt_GetSendStatus + IoTHubTransportMqtt_Create, + IoTHubTransportMqtt_Destroy, + IoTHubTransportMqtt_Subscribe, + IoTHubTransportMqtt_Unsubscribe, + IoTHubTransportMqtt_DoWork, + IoTHubTransportMqtt_GetSendStatus }; +/* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_022: [This function shall return a pointer to a structure of type TRANSPORT_PROVIDER having the following values for its fields: IoTHubTransport_Create = IoTHubTransportMqtt_Create +IoTHubTransport_Destroy = IoTHubTransportMqtt_Destroy +IoTHubTransport_Subscribe = IoTHubTransportMqtt_Subscribe +IoTHubTransport_Unsubscribe = IoTHubTransportMqtt_Unsubscribe +IoTHubTransport_DoWork = IoTHubTransportMqtt_DoWork +IoTHubTransport_SetOption = IoTHubTransportMqtt_SetOption] */ extern const void* MQTT_Protocol(void) { return &myfunc; diff --git a/c/iothub_client/tests/CMakeLists.txt b/c/iothub_client/tests/CMakeLists.txt index 5ad7a280..8f211efc 100644 --- a/c/iothub_client/tests/CMakeLists.txt +++ b/c/iothub_client/tests/CMakeLists.txt @@ -18,16 +18,16 @@ endif() if(${use_http}) add_subdirectory(iothubtransporthttp_unittests) if(${use_amqp}) - add_subdirectory(iothubclient_http_e2etests) - endif() + add_subdirectory(iothubclient_http_e2etests) +endif() endif() if(${use_mqtt}) add_subdirectory(iothubtransportmqtt_unittests) if(${use_amqp}) - add_subdirectory(iothubclient_mqtt_e2etests) + add_subdirectory(iothubclient_mqtt_e2etests) endif() - add_subdirectory(mqttapi_paho_unittests) + endif() add_subdirectory(version_unittests) \ No newline at end of file diff --git a/c/iothub_client/tests/iothubclient_mqtt_e2etests/CMakeLists.txt b/c/iothub_client/tests/iothubclient_mqtt_e2etests/CMakeLists.txt index a2c8b122..7e90595c 100644 --- a/c/iothub_client/tests/iothubclient_mqtt_e2etests/CMakeLists.txt +++ b/c/iothub_client/tests/iothubclient_mqtt_e2etests/CMakeLists.txt @@ -35,7 +35,7 @@ if(WIN32) iothub_client_mqtt_transport ) linkProton(${theseTestsName}_dll) - linkPaho(${theseTestsName}_dll) + linkMqttLibrary(${theseTestsName}_dll) endif() if(TARGET ${theseTestsName}_exe) @@ -47,7 +47,7 @@ if(WIN32) iothub_client_mqtt_transport ) linkProton(${theseTestsName}_exe) - linkPaho(${theseTestsName}_exe) + linkMqttLibrary(${theseTestsName}_exe) endif() else() if(TARGET ${theseTestsName}_exe) @@ -60,7 +60,6 @@ else() ) target_link_libraries(${theseTestsName}_exe pthread) linkProton(${theseTestsName}_exe) - linkPaho(${theseTestsName}_exe) + linkMqttLibrary(${theseTestsName}_exe) endif() endif() - diff --git a/c/iothub_client/tests/iothubclient_mqtt_e2etests/iothubclient_mqtt_e2etests.cpp b/c/iothub_client/tests/iothubclient_mqtt_e2etests/iothubclient_mqtt_e2etests.cpp index 09aa715e..786c6853 100644 --- a/c/iothub_client/tests/iothubclient_mqtt_e2etests/iothubclient_mqtt_e2etests.cpp +++ b/c/iothub_client/tests/iothubclient_mqtt_e2etests/iothubclient_mqtt_e2etests.cpp @@ -20,6 +20,16 @@ #include "buffer_.h" #include "threadapi.h" +#if _WIN32 +#include "tlsio_schannel.h" +#else +#ifdef MBED_BUILD_TIMESTAMP +#include "tlsio_wolfssl.h" +#else +#include "tlsio_openssl.h" +#endif +#endif + static MICROMOCK_GLOBAL_SEMAPHORE_HANDLE g_dllByDll; static bool g_callbackRecv = false; @@ -28,9 +38,10 @@ const char* TEST_MESSAGE_DATA_FMT = "{\"notifyData\":\"%.24s\",\"id\":\"%d\"}"; static size_t g_iotHubTestId = 0; -#define IOTHUB_COUNTER_MAX 10 -#define IOTHUB_TIMEOUT_SEC 1000 -#define MAX_CLOUD_TRAVEL_TIME 60.0 +#define IOTHUB_COUNTER_MAX 10 +#define IOTHUB_TIMEOUT_SEC 1000 +#define MAX_CLOUD_TRAVEL_TIME 60.0 +#define TEMP_BUFFER_SIZE 1024 DEFINE_MICROMOCK_ENUM_TO_STRING(IOTHUB_TEST_CLIENT_RESULT, IOTHUB_TEST_CLIENT_RESULT_VALUES); DEFINE_MICROMOCK_ENUM_TO_STRING(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUES); @@ -55,6 +66,23 @@ typedef struct EXPECTED_RECEIVE_DATA_TAG BEGIN_TEST_SUITE(iothubclient_mqtt_e2etests) + static XIO_HANDLE CreateXioConnection(const char* hostname, int portNum) + { +#if _WIN32 + TLSIO_SCHANNEL_CONFIG tls_io_config = { hostname, portNum }; + const IO_INTERFACE_DESCRIPTION* tlsio_interface = tlsio_schannel_get_interface_description(); +#else +#ifdef MBED_BUILD_TIMESTAMP + TLSIO_WOLFSSL_CONFIG tls_io_config = { hostname, portNum }; + const IO_INTERFACE_DESCRIPTION* tlsio_interface = tlsio_wolfssl_get_interface_description(); +#else + TLSIO_OPENSSL_CONFIG tls_io_config = { hostname, portNum }; + const IO_INTERFACE_DESCRIPTION* tlsio_interface = tlsio_openssl_get_interface_description(); +#endif +#endif + return xio_create(tlsio_interface, &tls_io_config, NULL); + } + static int IoTHubCallback(void* context, const char* data, size_t size) { size; @@ -132,10 +160,10 @@ BEGIN_TEST_SUITE(iothubclient_mqtt_e2etests) EXPECTED_RECEIVE_DATA* result = (EXPECTED_RECEIVE_DATA*)malloc(sizeof(EXPECTED_RECEIVE_DATA)); if (result != NULL) { - char temp[1000]; + char temp[TEMP_BUFFER_SIZE]; char* tempString; time_t t = time(NULL); - sprintf(temp, TEST_MESSAGE_DATA_FMT, ctime(&t), g_iotHubTestId); + (void)snprintf(temp, TEMP_BUFFER_SIZE, TEST_MESSAGE_DATA_FMT, ctime(&t), g_iotHubTestId); if ( (tempString = (char*)malloc(strlen(temp) + 1) ) == NULL) { free(result); @@ -184,10 +212,10 @@ BEGIN_TEST_SUITE(iothubclient_mqtt_e2etests) EXPECTED_SEND_DATA* result = (EXPECTED_SEND_DATA*)malloc(sizeof(EXPECTED_SEND_DATA)); if (result != NULL) { - char temp[1000]; + char temp[TEMP_BUFFER_SIZE]; char* tempString; time_t t = time(NULL); - sprintf(temp, TEST_EVENT_DATA_FMT, ctime(&t), g_iotHubTestId); + (void)snprintf(temp, TEMP_BUFFER_SIZE, TEST_EVENT_DATA_FMT, ctime(&t), g_iotHubTestId); if ( (tempString = (char*)malloc(strlen(temp) + 1) ) == NULL) { free(result); @@ -235,123 +263,122 @@ BEGIN_TEST_SUITE(iothubclient_mqtt_e2etests) { } - //Disabling MQTT e2e tests, pending fix of Bug 480363 - MQTT- C Client not cleaning Open SSL Properly, causing crashes - //TEST_FUNCTION(IoTHub_MQTT_SendEvent_E2ETests) - //{ - // // arrange - // IOTHUB_CLIENT_CONFIG iotHubConfig; - // IOTHUB_CLIENT_HANDLE iotHubClientHandle; - // IOTHUB_MESSAGE_HANDLE msgHandle; + // Will enable as soon as it's ready + TEST_FUNCTION(IoTHub_MQTT_SendEvent_E2ETests) + { + // arrange + IOTHUB_CLIENT_CONFIG iotHubConfig; + IOTHUB_CLIENT_HANDLE iotHubClientHandle; + IOTHUB_MESSAGE_HANDLE msgHandle; - // iotHubConfig.iotHubName = IoTHubAccount_GetIoTHubName(); - // iotHubConfig.iotHubSuffix = IoTHubAccount_GetIoTHubSuffix(); - // iotHubConfig.deviceId = IoTHubAccount_GetDeviceId(); - // iotHubConfig.deviceKey = IoTHubAccount_GetDeviceKey(); - // iotHubConfig.protocolGatewayHostName = IoTHubAccount_GetProtocolGatewayHostName(); - // iotHubConfig.protocol = MQTT_Protocol; + iotHubConfig.iotHubName = IoTHubAccount_GetIoTHubName(); + iotHubConfig.iotHubSuffix = IoTHubAccount_GetIoTHubSuffix(); + iotHubConfig.deviceId = IoTHubAccount_GetDeviceId(); + iotHubConfig.deviceKey = IoTHubAccount_GetDeviceKey(); + iotHubConfig.protocolGatewayHostName = IoTHubAccount_GetProtocolGatewayHostName(); + iotHubConfig.protocol = MQTT_Protocol; - // EXPECTED_SEND_DATA* sendData = EventData_Create(); - // ASSERT_IS_NOT_NULL(sendData); + EXPECTED_SEND_DATA* sendData = EventData_Create(); + ASSERT_IS_NOT_NULL(sendData); - // // Send the Event - // { - // IOTHUB_CLIENT_RESULT result; - // // Create the IoT Hub Data - // iotHubClientHandle = IoTHubClient_Create(&iotHubConfig); - // ASSERT_IS_NOT_NULL_WITH_MSG(iotHubClientHandle,"Could not create IoTHubClient."); + // Send the Event + { + IOTHUB_CLIENT_RESULT result; + // Create the IoT Hub Data + iotHubClientHandle = IoTHubClient_Create(&iotHubConfig); + ASSERT_IS_NOT_NULL_WITH_MSG(iotHubClientHandle,"Could not create IoTHubClient."); - // msgHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)sendData->expectedString, strlen(sendData->expectedString)); - // ASSERT_IS_NOT_NULL_WITH_MSG(msgHandle, "Error Creating IoTHubMEssage From Byte Array."); + msgHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)sendData->expectedString, strlen(sendData->expectedString)); + ASSERT_IS_NOT_NULL_WITH_MSG(msgHandle, "Error Creating IoTHubMEssage From Byte Array."); - // // act - // result = IoTHubClient_SendEventAsync(iotHubClientHandle, msgHandle, ReceiveConfirmationCallback, sendData); - // ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result); - // } + // act + result = IoTHubClient_SendEventAsync(iotHubClientHandle, msgHandle, ReceiveConfirmationCallback, sendData); + ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result); + } - // time_t beginOperation, nowTime; - // beginOperation = time(NULL); - // while ( - // ( - // (nowTime = time(NULL)), - // (difftime(nowTime, beginOperation) < MAX_CLOUD_TRAVEL_TIME) // time box - // ) && - // (!sendData->dataWasRecv) // Condition box - // ) - // { - // // Just go on here - // } - // ASSERT_IS_TRUE(sendData->dataWasRecv); // was found is written by the callback... - // IoTHubClient_Destroy(iotHubClientHandle); + time_t beginOperation, nowTime; + beginOperation = time(NULL); + while ( + ( + (nowTime = time(NULL)), + (difftime(nowTime, beginOperation) < MAX_CLOUD_TRAVEL_TIME) // time box + ) && + (!sendData->dataWasRecv) // Condition box + ) + { + // Just go on here + } + ASSERT_IS_TRUE(sendData->dataWasRecv); // was found is written by the callback... + IoTHubClient_Destroy(iotHubClientHandle); - // { - // IOTHUB_TEST_HANDLE iotHubTestHandle = IoTHubTest_Initialize(IoTHubAccount_GetEventHubConnectionString(), IoTHubAccount_GetIoTHubConnString(), IoTHubAccount_GetDeviceId(), IoTHubAccount_GetDeviceKey(), IoTHubAccount_GetEventhubListenName(), IoTHubAccount_GetEventhubAccessKey(), IoTHubAccount_GetSharedAccessSignature(), IoTHubAccount_GetEventhubConsumerGroup()); - // ASSERT_IS_NOT_NULL_WITH_MSG(iotHubTestHandle, "Problem Initializing IoTHub Test."); + { + IOTHUB_TEST_HANDLE iotHubTestHandle = IoTHubTest_Initialize(IoTHubAccount_GetEventHubConnectionString(), IoTHubAccount_GetIoTHubConnString(), IoTHubAccount_GetDeviceId(), IoTHubAccount_GetDeviceKey(), IoTHubAccount_GetEventhubListenName(), IoTHubAccount_GetEventhubAccessKey(), IoTHubAccount_GetSharedAccessSignature(), IoTHubAccount_GetEventhubConsumerGroup()); + ASSERT_IS_NOT_NULL_WITH_MSG(iotHubTestHandle, "Problem Initializing IoTHub Test."); - // IOTHUB_TEST_CLIENT_RESULT result = IoTHubTest_ListenForEventForMaxDrainTime(iotHubTestHandle, IoTHubCallback, IoTHubAccount_GetIoTHubPartitionCount(), sendData); - // ASSERT_ARE_EQUAL(IOTHUB_TEST_CLIENT_RESULT, IOTHUB_TEST_CLIENT_OK, result); + IOTHUB_TEST_CLIENT_RESULT result = IoTHubTest_ListenForEventForMaxDrainTime(iotHubTestHandle, IoTHubCallback, IoTHubAccount_GetIoTHubPartitionCount(), sendData); + ASSERT_ARE_EQUAL(IOTHUB_TEST_CLIENT_RESULT, IOTHUB_TEST_CLIENT_OK, result); - // IoTHubTest_Deinit(iotHubTestHandle); - // } + IoTHubTest_Deinit(iotHubTestHandle); + } - // // assert - // ASSERT_IS_TRUE(sendData->wasFound); // was found is written by the callback... + // assert + ASSERT_IS_TRUE(sendData->wasFound); // was found is written by the callback... - // // cleanup - // IoTHubMessage_Destroy(msgHandle); - // EventData_Destroy(sendData); - //} + // cleanup + IoTHubMessage_Destroy(msgHandle); + EventData_Destroy(sendData); + } - //TEST_FUNCTION(IoTHub_MQTT_RecvMessage_E2ETest) - //{ - // // arrange - // IOTHUB_CLIENT_CONFIG iotHubConfig; - // IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle; + TEST_FUNCTION(IoTHub_MQTT_RecvMessage_E2ETest) + { + // arrange + IOTHUB_CLIENT_CONFIG iotHubConfig; + IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle; - // EXPECTED_RECEIVE_DATA* notifyData = MessageData_Create(); - // ASSERT_IS_NOT_NULL_WITH_MSG(notifyData, "Error creating Notify Data."); + EXPECTED_RECEIVE_DATA* notifyData = MessageData_Create(); + ASSERT_IS_NOT_NULL_WITH_MSG(notifyData, "Error creating Notify Data."); - // // act - // iotHubConfig.iotHubName = IoTHubAccount_GetIoTHubName(); - // iotHubConfig.iotHubSuffix = IoTHubAccount_GetIoTHubSuffix(); - // iotHubConfig.deviceId = IoTHubAccount_GetDeviceId(); - // iotHubConfig.deviceKey = IoTHubAccount_GetDeviceKey(); - // iotHubConfig.protocolGatewayHostName = IoTHubAccount_GetProtocolGatewayHostName(); - // iotHubConfig.protocol = MQTT_Protocol; + // act + iotHubConfig.iotHubName = IoTHubAccount_GetIoTHubName(); + iotHubConfig.iotHubSuffix = IoTHubAccount_GetIoTHubSuffix(); + iotHubConfig.deviceId = IoTHubAccount_GetDeviceId(); + iotHubConfig.deviceKey = IoTHubAccount_GetDeviceKey(); + iotHubConfig.protocolGatewayHostName = IoTHubAccount_GetProtocolGatewayHostName(); + iotHubConfig.protocol = MQTT_Protocol; + iotHubClientHandle = IoTHubClient_Create(&iotHubConfig); + ASSERT_IS_NOT_NULL_WITH_MSG(iotHubClientHandle, "Error creating IoTHubClient."); - // iotHubClientHandle = IoTHubClient_Create(&iotHubConfig); - // ASSERT_IS_NOT_NULL_WITH_MSG(iotHubClientHandle, "Error creating IoTHubClient."); + IOTHUB_CLIENT_RESULT result = IoTHubClient_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, notifyData); + ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result); - // IOTHUB_CLIENT_RESULT result = IoTHubClient_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, notifyData); - // ASSERT_ARE_EQUAL(int, IOTHUB_CLIENT_OK, result); + IOTHUB_TEST_HANDLE iotHubTestHandle = IoTHubTest_Initialize(IoTHubAccount_GetEventHubConnectionString(), IoTHubAccount_GetIoTHubConnString(), IoTHubAccount_GetDeviceId(), IoTHubAccount_GetDeviceKey(), IoTHubAccount_GetEventhubListenName(), IoTHubAccount_GetEventhubAccessKey(), IoTHubAccount_GetSharedAccessSignature(), IoTHubAccount_GetEventhubConsumerGroup()); + ASSERT_IS_NOT_NULL_WITH_MSG(iotHubTestHandle, "Error Creating IotHubTest."); - // IOTHUB_TEST_HANDLE iotHubTestHandle = IoTHubTest_Initialize(IoTHubAccount_GetEventHubConnectionString(), IoTHubAccount_GetIoTHubConnString(), IoTHubAccount_GetDeviceId(), IoTHubAccount_GetDeviceKey(), IoTHubAccount_GetEventhubListenName(), IoTHubAccount_GetEventhubAccessKey(), IoTHubAccount_GetSharedAccessSignature(), IoTHubAccount_GetEventhubConsumerGroup()); - // ASSERT_IS_NOT_NULL_WITH_MSG(iotHubTestHandle, "Error Creating IotHubTest."); + IOTHUB_TEST_CLIENT_RESULT testResult = IoTHubTest_SendMessage(iotHubTestHandle, notifyData->toBeSend, notifyData->toBeSendSize); + ASSERT_ARE_EQUAL(IOTHUB_TEST_CLIENT_RESULT, IOTHUB_TEST_CLIENT_OK, testResult); - // IOTHUB_TEST_CLIENT_RESULT testResult = IoTHubTest_SendMessage(iotHubTestHandle, notifyData->toBeSend, notifyData->toBeSendSize); - // ASSERT_ARE_EQUAL(IOTHUB_TEST_CLIENT_RESULT, IOTHUB_TEST_CLIENT_OK, testResult); + IoTHubTest_Deinit(iotHubTestHandle); - // IoTHubTest_Deinit(iotHubTestHandle); + time_t beginOperation, nowTime; + beginOperation = time(NULL); + while ( + ( + (nowTime = time(NULL)), + (difftime(nowTime, beginOperation) < MAX_CLOUD_TRAVEL_TIME) //time box + ) && + (!notifyData->wasFound) //condition box + ) + { + //just go on; + } - // time_t beginOperation, nowTime; - // beginOperation = time(NULL); - // while ( - // ( - // (nowTime = time(NULL)), - // (difftime(nowTime, beginOperation) < MAX_CLOUD_TRAVEL_TIME) //time box - // ) && - // (!notifyData->wasFound) //condition box - // ) - // { - // //just go on; - // } - - // // assert - // ASSERT_IS_TRUE(notifyData->wasFound); // was found is written by the callback... - - // // cleanup - // MessageData_Destroy(notifyData); - // IoTHubClient_Destroy(iotHubClientHandle); - //} + // assert + ASSERT_IS_TRUE(notifyData->wasFound); // was found is written by the callback... + + // cleanup + MessageData_Destroy(notifyData); + IoTHubClient_Destroy(iotHubClientHandle); + } END_TEST_SUITE(iothubclient_mqtt_e2etests) diff --git a/c/iothub_client/tests/iothubtransportmqtt_unittests/CMakeLists.txt b/c/iothub_client/tests/iothubtransportmqtt_unittests/CMakeLists.txt index 05c9a9d0..b3ea6765 100644 --- a/c/iothub_client/tests/iothubtransportmqtt_unittests/CMakeLists.txt +++ b/c/iothub_client/tests/iothubtransportmqtt_unittests/CMakeLists.txt @@ -22,4 +22,4 @@ set(${theseTestsName}_c_files set(${theseTestsName}_h_files ) -build_test_artifacts(${theseTestsName} ON) \ No newline at end of file +build_test_artifacts(${theseTestsName} ON) diff --git a/c/iothub_client/tests/iothubtransportmqtt_unittests/iothubtransportmqtt_unittests.cpp b/c/iothub_client/tests/iothubtransportmqtt_unittests/iothubtransportmqtt_unittests.cpp index 55227053..9fef9592 100644 --- a/c/iothub_client/tests/iothubtransportmqtt_unittests/iothubtransportmqtt_unittests.cpp +++ b/c/iothub_client/tests/iothubtransportmqtt_unittests/iothubtransportmqtt_unittests.cpp @@ -8,13 +8,14 @@ #include +#include "sastoken.h" #include "testrunnerswitcher.h" #include "micromock.h" #include "micromockcharstararenullterminatedstrings.h" #include "doublylinkedlist.h" #include "strings.h" -#include "mqttapi.h" +#include "mqtt_client.h" #include "macro_utils.h" #undef DEFINE_ENUM @@ -23,6 +24,10 @@ #include "iothubtransportmqtt.h" #include "iothub_client_private.h" +#include "tlsio_schannel.h" +#include "tlsio_wolfssl.h" +#include "tlsio_openssl.h" + #define GBALLOC_H extern "C" int gballoc_init(void); extern "C" void gballoc_deinit(void); @@ -31,46 +36,64 @@ extern "C" void* gballoc_calloc(size_t nmemb, size_t size); extern "C" void* gballoc_realloc(void* ptr, size_t size); extern "C" void gballoc_free(void* ptr); +static const char* TEST_DEVICE_ID = "thisIsDeviceID"; +static const char* TEST_DEVICE_KEY = "thisIsDeviceKey"; +static const char* TEST_IOTHUB_NAME = "thisIsIotHubName"; +static const char* TEST_IOTHUB_SUFFIX = "thisIsIotHubSuffix"; +static const char* TEST_PROTOCOL_GATEWAY_HOSTNAME = "ssl://thisIsAGatewayHostName.net"; +static const char* TEST_VERY_LONG_DEVICE_ID = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; +static const char* TEST_MQTT_MESSAGE_TOPIC = "devices/thisIsDeviceID/messages/devicebound"; +static const char* TEST_MQTT_EVENT_TOPIC = "devices/thisIsDeviceID/messages/events"; +static const char* TEST_MQTT_SAS_TOKEN = "thisIsIotHubName.thisIsIotHubSuffix/devices/thisIsDeviceID"; +static const char* TEST_HOST_NAME = "thisIsIotHubName.thisIsIotHubSuffix"; +static const char* TEST_EMPTY_STRING = ""; +static const char* TEST_SAS_TOKEN = "Test_SAS_Token_value"; +static const char* LOG_TRACE_OPTION = "logtrace"; -#define TEST_DEVICE_ID "thisIsDeviceID" -#define TEST_DEVICE_KEY "thisIsDeviceKey" -#define TEST_IOTHUB_NAME "thisIsIotHubName" -#define TEST_IOTHUB_SUFFIX "thisIsIotHubSuffix" -#define TEST_PROTOCOL_GATEWAY_HOSTNAME "thisIsAGatewayHostName" -#define TEST_VERY_LONG_DEVICE_ID "blablablablablablasd;flaksdjf;laskdfjal;sdkfjasdlfkjasdlfkjdslkfalsdkfjasdlkfjasldkfjasdlkfjasldkfjasldkfjasdlkfjadslkfjasldkfjl;ajsdf" -#define TEST_MQTTAPI_HANDLE (MQTTAPI_HANDLE)0x4242 -#define TEST_IOTHUB_CLIENT_LL_HANDLE (IOTHUB_CLIENT_LL_HANDLE)0x4343 -#define TEST_TRANSPORT_HANDLE (TRANSPORT_HANDLE)0x4444 -#define TEST_MQTTAPI_TOPIC_HANDLE (MQTTAPI_TOPIC_HANDLE)0x4545 -#define TEST_MQTTAPI_MESSAGE_TOPIC "devices/thisIsDeviceID/messages/devicebound" -#define TEST_MQTTAPI_EVENT_TOPIC "devices/thisIsDeviceID/messages/events" -#define TEST_DEFAULT_QOS_VALUE 1 +static const IOTHUB_CLIENT_LL_HANDLE TEST_IOTHUB_CLIENT_LL_HANDLE = (IOTHUB_CLIENT_LL_HANDLE)0x4343; +static const TRANSPORT_HANDLE TEST_TRANSPORT_HANDLE = (TRANSPORT_HANDLE)0x4444; +static const MQTT_CLIENT_HANDLE TEST_MQTT_CLIENT_HANDLE = (MQTT_CLIENT_HANDLE)0x1122; +static const PDLIST_ENTRY TEST_PDLIST_ENTRY = (PDLIST_ENTRY)0x1123; +static const MQTT_MESSAGE_HANDLE TEST_MQTT_MESSAGE_HANDLE = (MQTT_MESSAGE_HANDLE)0x1124; + +static IO_INTERFACE_DESCRIPTION* TEST_IO_INTERFACE = (IO_INTERFACE_DESCRIPTION*)0x1125; +static XIO_HANDLE TEST_XIO_HANDLE = (XIO_HANDLE)0x1126; /*this is the default message and has type BYTEARRAY*/ -#define TEST_IOTHUB_MESSAGE_HANDLE_1 ((IOTHUB_MESSAGE_HANDLE)0x01d1) +static IOTHUB_MESSAGE_HANDLE TEST_IOTHUB_MSG_BYTEARRAY = (IOTHUB_MESSAGE_HANDLE)0x01d1; /*this is a STRING type message*/ -#define TEST_IOTHUB_MESSAGE_HANDLE_2 ((IOTHUB_MESSAGE_HANDLE)0x01d2) +static IOTHUB_MESSAGE_HANDLE TEST_IOTHUB_MSG_STRING = (IOTHUB_MESSAGE_HANDLE)0x01d2; -static unsigned char buffer1[1] = { '1' }; -static const size_t buffer1_size = sizeof(buffer1); +static char appMessageString[] = "App Message String"; +static uint8_t appMessage[] = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x4d, 0x73, 0x67 }; +static const size_t appMsgSize = sizeof(appMessage) / sizeof(appMessage[0]); +static IOTHUB_CLIENT_CONFIG g_iothubClientConfig = { 0 }; +static DLIST_ENTRY g_waitingToSend; + +#define TEST_TIME_T ((time_t)-1) //Messages to be used in test -static IOTHUB_MESSAGE_LIST message1 = /*this is the oldest message, always the first to be processed, send etc*/ +static IOTHUB_MESSAGE_LIST message1 = /* this is the oldest message, always the first to be processed, send etc*/ { - TEST_IOTHUB_MESSAGE_HANDLE_1, /*IOTHUB_MESSAGE_HANDLE messageHandle; */ - NULL, /*IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK callback; */ - NULL, /*void* context; */ - { NULL, NULL } /*DLIST_ENTRY entry; */ + TEST_IOTHUB_MSG_BYTEARRAY, /* IOTHUB_MESSAGE_HANDLE messageHandle; */ + NULL, /* IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK callback; */ + NULL, /* void* context; */ + { NULL, NULL } /* DLIST_ENTRY entry; */ }; -static IOTHUB_MESSAGE_LIST message2 = /*this is the oldest message, always the first to be processed, send etc*/ +static IOTHUB_MESSAGE_LIST message2 = /* this is the oldest message, always the first to be processed, send etc*/ { - TEST_IOTHUB_MESSAGE_HANDLE_2, /*IOTHUB_MESSAGE_HANDLE messageHandle; */ - NULL, /*IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK callback; */ - NULL, /*void* context; */ - { NULL, NULL } /*DLIST_ENTRY entry; */ + TEST_IOTHUB_MSG_STRING, /* IOTHUB_MESSAGE_HANDLE messageHandle; */ + NULL, /* IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK callback; */ + NULL, /* void* context; */ + { NULL, NULL } /* DLIST_ENTRY entry; */ +}; + +static APP_PAYLOAD_TAG TEST_APP_PAYLOAD = +{ + appMessage, appMsgSize }; DEFINE_MICROMOCK_ENUM_TO_STRING(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUES); @@ -93,7 +116,6 @@ namespace BASEIMPLEMENTATION #include "buffer.c" #include "base64.c" #include "map.c" - }; static MICROMOCK_MUTEX_HANDLE g_testByTest; @@ -108,223 +130,10 @@ static size_t whenShallSTRING_construct_fail; static size_t currentSTRING_concat_call; static size_t whenShallSTRING_concat_fail; - - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG= -{ - MQTT_Protocol, /* IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - TEST_DEVICE_ID,/*const char* deviceId; */ - TEST_DEVICE_KEY,/*const char* deviceKey; */ - TEST_IOTHUB_NAME,/*const char* iotHubName; */ - TEST_IOTHUB_SUFFIX,/* const char* iotHubSuffix; */ - TEST_PROTOCOL_GATEWAY_HOSTNAME /*const char* protocolGatewayHostName; */ -}; - -static DLIST_ENTRY waitingToSend; - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_PROTOCOL = -{ - NULL, /*IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - TEST_DEVICE_ID,/*const char* deviceId; */ - TEST_DEVICE_KEY,/*const char* deviceKey; */ - TEST_IOTHUB_NAME,/*const char* iotHubName; */ - TEST_IOTHUB_SUFFIX,/* const char* iotHubSuffix; */ - TEST_PROTOCOL_GATEWAY_HOSTNAME /*const char* protocolGatewayHostName; */ -}; - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_DEVICE_ID = -{ - MQTT_Protocol, /*IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - NULL,/*const char* deviceId; */ - TEST_DEVICE_KEY,/*const char* deviceKey; */ - TEST_IOTHUB_NAME,/*const char* iotHubName; */ - TEST_IOTHUB_SUFFIX,/* const char* iotHubSuffix; */ - TEST_PROTOCOL_GATEWAY_HOSTNAME /*const char* protocolGatewayHostName; */ -}; - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_DEVICE_KEY = -{ - MQTT_Protocol, /* IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - TEST_DEVICE_ID, /* const char* deviceId; */ - NULL, /* const char* deviceKey; */ - TEST_IOTHUB_NAME, /* const char* iotHubName; */ - TEST_IOTHUB_SUFFIX, /* const char* iotHubSuffix; */ - TEST_PROTOCOL_GATEWAY_HOSTNAME /*const char* protocolGatewayHostName; */ -}; - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_IOTHUB_NAME = -{ - MQTT_Protocol, /*IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - TEST_DEVICE_ID, /*const char* deviceId; */ - TEST_DEVICE_KEY, /*const char* deviceKey; */ - NULL, /*const char* iotHubName; */ - TEST_IOTHUB_SUFFIX, /* const char* iotHubSuffix; */ - TEST_PROTOCOL_GATEWAY_HOSTNAME /*const char* protocolGatewayHostName; */ -}; - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_IOTHUB_SUFFIX = -{ - MQTT_Protocol, /* IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - TEST_DEVICE_ID, /* const char* deviceId; */ - TEST_DEVICE_KEY, /* const char* deviceKey; */ - TEST_IOTHUB_NAME, /* const char* iotHubName; */ - NULL, /* const char* iotHubSuffix; */ - TEST_PROTOCOL_GATEWAY_HOSTNAME /*const char* protocolGatewayHostName; */ -}; - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_PROTOCOL_GATEWAY_HOSTNAME = -{ - MQTT_Protocol, /* IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - TEST_DEVICE_ID, /* const char* deviceId; */ - TEST_DEVICE_KEY, /* const char* deviceKey; */ - TEST_IOTHUB_NAME, /* const char* iotHubName; */ - TEST_IOTHUB_SUFFIX, /* const char* iotHubSuffix; */ - NULL /*const char* protocolGatewayHostName; */ -}; - - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_VERY_LONG_DEVICE_ID = -{ - MQTT_Protocol, /* IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - TEST_VERY_LONG_DEVICE_ID, /* const char* deviceId; */ - TEST_DEVICE_KEY, /* const char* deviceKey; */ - TEST_IOTHUB_NAME, /* const char* iotHubName; */ - TEST_IOTHUB_SUFFIX, /* const char* iotHubSuffix; */ - TEST_PROTOCOL_GATEWAY_HOSTNAME /*const char* protocolGatewayHostName; */ -}; - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_EMPTY_DEVICE_ID = -{ - MQTT_Protocol, /* IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - "", /* const char* deviceId; */ - TEST_DEVICE_KEY, /* const char* deviceKey; */ - TEST_IOTHUB_NAME, /* const char* iotHubName; */ - TEST_IOTHUB_SUFFIX, /* const char* iotHubSuffix; */ - TEST_PROTOCOL_GATEWAY_HOSTNAME /*const char* protocolGatewayHostName; */ -}; - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_EMPTY_DEVICE_KEY = -{ - MQTT_Protocol, /* IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - TEST_DEVICE_ID, /* const char* deviceId; */ - "", /* const char* deviceKey; */ - TEST_IOTHUB_NAME, /* const char* iotHubName; */ - TEST_IOTHUB_SUFFIX, /* const char* iotHubSuffix; */ - TEST_PROTOCOL_GATEWAY_HOSTNAME /*const char* protocolGatewayHostName; */ -}; - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_EMPTY_IOTHUB_NAME = -{ - MQTT_Protocol, /* IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - TEST_DEVICE_ID, /* const char* deviceId; */ - TEST_DEVICE_KEY, /* const char* deviceKey; */ - "", /* const char* iotHubName; */ - TEST_IOTHUB_SUFFIX, /* const char* iotHubSuffix; */ - TEST_PROTOCOL_GATEWAY_HOSTNAME /*const char* protocolGatewayHostName; */ -}; - -static const IOTHUB_CLIENT_CONFIG TEST_CONFIG_IOTHUBCLIENT_CONFIG_EMPTY_PROTOCOL_GATEWAY_HOSTNAME = -{ - MQTT_Protocol, /* IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol; */ - TEST_DEVICE_ID, /* const char* deviceId; */ - TEST_DEVICE_KEY, /* const char* deviceKey; */ - TEST_IOTHUB_NAME, /* const char* iotHubName; */ - TEST_IOTHUB_SUFFIX, /* const char* iotHubSuffix; */ - "" /*const char* protocolGatewayHostName; */ -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG, - &waitingToSend -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_NULL_WAITING_TO_SEND -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG, - NULL -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_NULL_CONFIG -{ - NULL, - (PDLIST_ENTRY)0x1 -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_NULL_PROTOCOL -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_PROTOCOL, - (PDLIST_ENTRY)0x1 -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_NULL_DEVICE_ID -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_DEVICE_ID, - (PDLIST_ENTRY)0x1 -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_NULL_DEVICE_KEY -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_DEVICE_KEY, - (PDLIST_ENTRY)0x1 -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_NULL_IOTHUB_NAME -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_IOTHUB_NAME, - (PDLIST_ENTRY)0x1 -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_NULL_IOTHUB_SUFFIX -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_IOTHUB_SUFFIX, - (PDLIST_ENTRY)0x1 -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_NULL_PROTOCOL_GATEWAY_HOSTNAME -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_NULL_PROTOCOL_GATEWAY_HOSTNAME, - (PDLIST_ENTRY)0x1 -}; - - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_VERY_LONG_DEVICE_ID -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_VERY_LONG_DEVICE_ID, - (PDLIST_ENTRY)0x1 -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_EMPTY_DEVICE_ID -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_EMPTY_DEVICE_ID, - (PDLIST_ENTRY)0x1 -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_EMPTY_DEVICE_KEY -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_EMPTY_DEVICE_KEY, - (PDLIST_ENTRY)0x1 -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_EMPTY_IOTHUB_NAME -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_EMPTY_IOTHUB_NAME, - (PDLIST_ENTRY)0x1 -}; - -static IOTHUBTRANSPORT_CONFIG TEST_CONFIG_EMPTY_PROTOCOL_GATEWAY_HOSTNAME -{ - &TEST_CONFIG_IOTHUBCLIENT_CONFIG_EMPTY_PROTOCOL_GATEWAY_HOSTNAME, - (PDLIST_ENTRY)0x1 -}; - - //Callbacks for Testing -MQTTAPI_DeliveryComplete * testDeliverycompletedCallBack; -void* contextReceivedAtPublishMessage; - -MQTTAPI_MessageArrived * testMessageArrivedCallback; -void* contextMessageArrived; +ON_MQTT_MESSAGE_RECV_CALLBACK g_fnMqttMsgRecv; +ON_MQTT_OPERATION_CALLBACK g_fnMqttOperationCallback; +void* g_callbackCtx; TYPED_MOCK_CLASS(CIoTHubTransportMqttMocks, CGlobalMock) { @@ -334,28 +143,27 @@ public: BASEIMPLEMENTATION::DList_InitializeListHead(listHead); MOCK_VOID_METHOD_END() - MOCK_STATIC_METHOD_1(, int, DList_IsListEmpty, PDLIST_ENTRY, listHead) + MOCK_STATIC_METHOD_1(, int, DList_IsListEmpty, PDLIST_ENTRY, listHead) int result2 = BASEIMPLEMENTATION::DList_IsListEmpty(listHead); MOCK_METHOD_END(int, result2) - MOCK_STATIC_METHOD_2(, void, DList_InsertTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry) + MOCK_STATIC_METHOD_2(, void, DList_InsertTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry) BASEIMPLEMENTATION::DList_InsertTailList(listHead, listEntry); MOCK_VOID_METHOD_END() - MOCK_STATIC_METHOD_2(, void, DList_InsertHeadList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry) + MOCK_STATIC_METHOD_2(, void, DList_InsertHeadList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry) BASEIMPLEMENTATION::DList_InsertHeadList(listHead, listEntry); MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_2(, void, DList_AppendTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, ListToAppend) + MOCK_STATIC_METHOD_2(, void, DList_AppendTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, ListToAppend) BASEIMPLEMENTATION::DList_AppendTailList(listHead, ListToAppend); MOCK_VOID_METHOD_END() - MOCK_STATIC_METHOD_1(, int, DList_RemoveEntryList, PDLIST_ENTRY, listEntry) + MOCK_STATIC_METHOD_1(, int, DList_RemoveEntryList, PDLIST_ENTRY, listEntry) int result2 = BASEIMPLEMENTATION::DList_RemoveEntryList(listEntry); MOCK_METHOD_END(int, result2) - MOCK_STATIC_METHOD_1(, PDLIST_ENTRY, DList_RemoveHeadList, PDLIST_ENTRY, listHead) + MOCK_STATIC_METHOD_1(, PDLIST_ENTRY, DList_RemoveHeadList, PDLIST_ENTRY, listHead) PDLIST_ENTRY entry = BASEIMPLEMENTATION::DList_RemoveHeadList(listHead); MOCK_METHOD_END(PDLIST_ENTRY, entry) @@ -383,43 +191,44 @@ public: MOCK_METHOD_END(void*, result2); MOCK_STATIC_METHOD_2(, void*, gballoc_realloc, void*, ptr, size_t, size) - MOCK_METHOD_END(void*, BASEIMPLEMENTATION::gballoc_realloc(ptr, size)); + MOCK_METHOD_END(void*, BASEIMPLEMENTATION::gballoc_realloc(ptr, size)); MOCK_STATIC_METHOD_1(, void, gballoc_free, void*, ptr) BASEIMPLEMENTATION::gballoc_free(ptr); MOCK_VOID_METHOD_END() - MOCK_STATIC_METHOD_3(, void, eventConfirmationCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONFIRMATION_RESULT, result2, void*, userContextCallback) - MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_3(, int, messageCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, message, void*, userContextCallback) - MOCK_METHOD_END(int, 0); + MOCK_STATIC_METHOD_3(, void, eventConfirmationCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONFIRMATION_RESULT, result2, void*, userContextCallback) + MOCK_VOID_METHOD_END() + MOCK_STATIC_METHOD_3(, int, messageCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, message, void*, userContextCallback) + MOCK_METHOD_END(int, 0); /*Strings*/ + MOCK_STATIC_METHOD_0(, STRING_HANDLE, STRING_new) + MOCK_METHOD_END(STRING_HANDLE, BASEIMPLEMENTATION::STRING_new()) + MOCK_STATIC_METHOD_1(, STRING_HANDLE, STRING_construct, const char*, source) STRING_HANDLE result2; - currentSTRING_construct_call++; - if (whenShallSTRING_construct_fail > 0) - { - if (currentSTRING_construct_call == whenShallSTRING_construct_fail) + currentSTRING_construct_call++; + if (whenShallSTRING_construct_fail > 0) { - result2 = (STRING_HANDLE)NULL; + if (currentSTRING_construct_call == whenShallSTRING_construct_fail) + { + result2 = (STRING_HANDLE)NULL; + } + else + { + result2 = BASEIMPLEMENTATION::STRING_construct(source); + } } else { result2 = BASEIMPLEMENTATION::STRING_construct(source); } - } - else - { - result2 = BASEIMPLEMENTATION::STRING_construct(source); - } MOCK_METHOD_END(STRING_HANDLE, result2) - MOCK_STATIC_METHOD_2(, int, STRING_concat, STRING_HANDLE, s1, const char*, s2) - currentSTRING_concat_call++; + currentSTRING_concat_call++; MOCK_METHOD_END(int, (((whenShallSTRING_concat_fail > 0) && (currentSTRING_concat_call == whenShallSTRING_concat_fail)) ? __LINE__ : BASEIMPLEMENTATION::STRING_concat(s1, s2))); MOCK_STATIC_METHOD_1(, void, STRING_delete, STRING_HANDLE, s) @@ -429,7 +238,6 @@ public: MOCK_STATIC_METHOD_1(, const char*, STRING_c_str, STRING_HANDLE, s) MOCK_METHOD_END(const char*, BASEIMPLEMENTATION::STRING_c_str(s)) - /* IoTHubClient mocks*/ MOCK_STATIC_METHOD_2(, IOTHUBMESSAGE_DISPOSITION_RESULT, IoTHubClient_LL_MessageCallback, IOTHUB_CLIENT_LL_HANDLE, handle, IOTHUB_MESSAGE_HANDLE, message) MOCK_METHOD_END(IOTHUBMESSAGE_DISPOSITION_RESULT, IOTHUBMESSAGE_ACCEPTED) @@ -438,25 +246,27 @@ public: MOCK_VOID_METHOD_END() /* IoTHubMessage mocks */ - MOCK_STATIC_METHOD_1(, IOTHUBMESSAGE_CONTENT_TYPE, IoTHubMessage_GetContentType, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle) IOTHUBMESSAGE_CONTENT_TYPE result2; - if (iotHubMessageHandle == TEST_IOTHUB_MESSAGE_HANDLE_1) + if (iotHubMessageHandle == TEST_IOTHUB_MSG_BYTEARRAY) { result2 = IOTHUBMESSAGE_BYTEARRAY; } - else if (iotHubMessageHandle == TEST_IOTHUB_MESSAGE_HANDLE_2) + else if (iotHubMessageHandle == TEST_IOTHUB_MSG_STRING) { result2 = IOTHUBMESSAGE_STRING; } - + else + { + result2 = IOTHUBMESSAGE_UNKNOWN; + } MOCK_METHOD_END(IOTHUBMESSAGE_CONTENT_TYPE, result2) MOCK_STATIC_METHOD_1(, const char*, IoTHubMessage_GetString, IOTHUB_MESSAGE_HANDLE, handle) const char* result2; - if (handle == TEST_IOTHUB_MESSAGE_HANDLE_2) + if (handle == TEST_IOTHUB_MSG_STRING) { - result2 = "some text"; + result2 = appMessageString; } else { @@ -465,63 +275,87 @@ public: MOCK_METHOD_END(const char*, result2) MOCK_STATIC_METHOD_2(, IOTHUB_MESSAGE_HANDLE, IoTHubMessage_CreateFromByteArray, const unsigned char*, buffer, size_t, size) - MOCK_METHOD_END(IOTHUB_MESSAGE_HANDLE, (IOTHUB_MESSAGE_HANDLE)0x42) + MOCK_METHOD_END(IOTHUB_MESSAGE_HANDLE, TEST_IOTHUB_MSG_BYTEARRAY) - MOCK_STATIC_METHOD_3(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_GetByteArray, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const unsigned char**, buffer, size_t*, size) + MOCK_STATIC_METHOD_3(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_GetByteArray, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const unsigned char**, buffer, size_t*, size) { - switch ((uintptr_t)iotHubMessageHandle) + if (iotHubMessageHandle == TEST_IOTHUB_MSG_BYTEARRAY) { - case ((uintptr_t)TEST_IOTHUB_MESSAGE_HANDLE_1) : - { - *buffer = buffer1; - *size = buffer1_size; - break; + *buffer = appMessage; + *size = appMsgSize; } - default: + else { /*not expected really*/ *buffer = (const unsigned char*)"333"; *size = 3; } - } - } MOCK_METHOD_END(IOTHUB_MESSAGE_RESULT, IOTHUB_MESSAGE_OK) MOCK_STATIC_METHOD_1(, void, IoTHubMessage_Destroy, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle) MOCK_VOID_METHOD_END() - /* MQTTAPI Mocks*/ - MOCK_STATIC_METHOD_1(, MQTTAPI_HANDLE, MQTTAPI_Create, const MQTTAPI_ConnectOptions*, options) - MOCK_METHOD_END(MQTTAPI_HANDLE, TEST_MQTTAPI_HANDLE); + // Azure Mqtt + MOCK_STATIC_METHOD_4(, MQTT_CLIENT_HANDLE, mqtt_client_init, ON_MQTT_MESSAGE_RECV_CALLBACK, msgRecv, ON_MQTT_OPERATION_CALLBACK, opCallback, void*, callbackCtx, LOGGER_LOG, logger) + g_fnMqttMsgRecv = msgRecv; + g_fnMqttOperationCallback = opCallback; + g_callbackCtx = callbackCtx; + MOCK_METHOD_END(MQTT_CLIENT_HANDLE, TEST_MQTT_CLIENT_HANDLE); - MOCK_STATIC_METHOD_1(, void, MQTTAPI_Destroy, MQTTAPI_HANDLE, instance) + MOCK_STATIC_METHOD_3(, int, mqtt_client_connect, MQTT_CLIENT_HANDLE, handle, XIO_HANDLE, xioHandle, MQTT_CLIENT_OPTIONS*, mqttOptions) + MOCK_METHOD_END(int, 0); + + MOCK_STATIC_METHOD_1(, void, mqtt_client_deinit, MQTT_CLIENT_HANDLE, handle) + MOCK_VOID_METHOD_END(); + + MOCK_STATIC_METHOD_1(, int, mqtt_client_disconnect, MQTT_CLIENT_HANDLE, handle) + MOCK_METHOD_END(int, 0); + + MOCK_STATIC_METHOD_4(, int, mqtt_client_subscribe, MQTT_CLIENT_HANDLE, handle, uint16_t, packetId, SUBSCRIBE_PAYLOAD*, subscribeList, size_t, count) + MOCK_METHOD_END(int, 0); + + MOCK_STATIC_METHOD_4(, int, mqtt_client_unsubscribe, MQTT_CLIENT_HANDLE, handle, uint16_t, packetId, const char**, unsubscribeList, size_t, count) + MOCK_METHOD_END(int, 0); + + MOCK_STATIC_METHOD_2(, int, mqtt_client_publish, MQTT_CLIENT_HANDLE, handle, MQTT_MESSAGE_HANDLE, msgHandle) + MOCK_METHOD_END(int, 0); + + MOCK_STATIC_METHOD_1(, void, mqtt_client_dowork, MQTT_CLIENT_HANDLE, handle) MOCK_VOID_METHOD_END() - MOCK_STATIC_METHOD_2(, MQTTAPI_TOPIC_HANDLE, MQTTAPI_Subscribe, MQTTAPI_HANDLE, instance, const char*, topic) - MOCK_METHOD_END(MQTTAPI_TOPIC_HANDLE, TEST_MQTTAPI_TOPIC_HANDLE); - - MOCK_STATIC_METHOD_1(, void, MQTTAPI_Unsubscribe, MQTTAPI_TOPIC_HANDLE, topicInstance) - MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_4(, MQTTAPI_RESULT, MQTTAPI_PublishMessage, MQTTAPI_HANDLE, instance, const char*, topicName, const MQTTAPI_Message*, msg, void*, context) - contextReceivedAtPublishMessage = context; - MOCK_METHOD_END(MQTTAPI_RESULT, MQTTAPI_OK); - - MOCK_STATIC_METHOD_3(, MQTTAPI_RESULT, MQTTAPI_SetMessageCallback, MQTTAPI_HANDLE, instance, void*, context, MQTTAPI_MessageArrived *, ma) - testMessageArrivedCallback = ma; - contextMessageArrived = context; - MOCK_METHOD_END(MQTTAPI_RESULT, MQTTAPI_OK); - - MOCK_STATIC_METHOD_2(, MQTTAPI_RESULT, MQTTAPI_SetDeliveryCompletedCallback, MQTTAPI_HANDLE, instance, MQTTAPI_DeliveryComplete *, dc) - testDeliverycompletedCallBack = dc; - MOCK_METHOD_END(MQTTAPI_RESULT, MQTTAPI_OK); - - - MOCK_STATIC_METHOD_1(, void, MQTTAPI_DoWork, MQTTAPI_HANDLE, instance); + MOCK_STATIC_METHOD_2(, void, mqtt_client_set_trace, MQTT_CLIENT_HANDLE, handle, bool, traceVal) MOCK_VOID_METHOD_END() + + MOCK_STATIC_METHOD_5(, MQTT_MESSAGE_HANDLE, mqttmessage_create, uint16_t, packetId, const char*, topicName, QOS_VALUE, qosValue, const uint8_t*, appMsg, size_t, appMsgLength) + MOCK_METHOD_END(MQTT_MESSAGE_HANDLE, TEST_MQTT_MESSAGE_HANDLE); + + MOCK_STATIC_METHOD_1(, const APP_PAYLOAD*, mqttmessage_getApplicationMsg, MQTT_MESSAGE_HANDLE, handle) + MOCK_METHOD_END(const APP_PAYLOAD*, &TEST_APP_PAYLOAD); + + MOCK_STATIC_METHOD_1(, void, mqttmessage_destroy, MQTT_MESSAGE_HANDLE, handle); + MOCK_VOID_METHOD_END() + + MOCK_STATIC_METHOD_4(, STRING_HANDLE, SASToken_Create, STRING_HANDLE, key, STRING_HANDLE, scope, STRING_HANDLE, keyName, size_t, expiry) + MOCK_METHOD_END(STRING_HANDLE, BASEIMPLEMENTATION::STRING_construct(TEST_SAS_TOKEN) ); + + MOCK_STATIC_METHOD_1(, time_t, get_time, time_t*, currentTime) + MOCK_METHOD_END(time_t, TEST_TIME_T); + + MOCK_STATIC_METHOD_0(, const IO_INTERFACE_DESCRIPTION*, tlsio_schannel_get_interface_description) + MOCK_METHOD_END(const IO_INTERFACE_DESCRIPTION*, TEST_IO_INTERFACE); + + MOCK_STATIC_METHOD_0(, const IO_INTERFACE_DESCRIPTION*, tlsio_openssl_get_interface_description) + MOCK_METHOD_END(const IO_INTERFACE_DESCRIPTION*, TEST_IO_INTERFACE); + + MOCK_STATIC_METHOD_3(, XIO_HANDLE, xio_create, const IO_INTERFACE_DESCRIPTION*, io_interface_description, const void*, xio_create_parameters, LOGGER_LOG, logger_log) + MOCK_METHOD_END(XIO_HANDLE, TEST_XIO_HANDLE); }; +DECLARE_GLOBAL_MOCK_METHOD_0(CIoTHubTransportMqttMocks, , const IO_INTERFACE_DESCRIPTION*, tlsio_schannel_get_interface_description); +DECLARE_GLOBAL_MOCK_METHOD_0(CIoTHubTransportMqttMocks, , const IO_INTERFACE_DESCRIPTION*, tlsio_openssl_get_interface_description); +DECLARE_GLOBAL_MOCK_METHOD_3(CIoTHubTransportMqttMocks, , XIO_HANDLE, xio_create, const IO_INTERFACE_DESCRIPTION*, io_interface_description, const void*, xio_create_parameters, LOGGER_LOG, logger_log); + DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , void, DList_InitializeListHead, PDLIST_ENTRY, listHead); DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , int, DList_IsListEmpty, PDLIST_ENTRY, listHead); DECLARE_GLOBAL_MOCK_METHOD_2(CIoTHubTransportMqttMocks, , void, DList_InsertTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry); @@ -538,6 +372,7 @@ DECLARE_GLOBAL_MOCK_METHOD_2(CIoTHubTransportMqttMocks, , int, mallocAndStrcpy_s DECLARE_GLOBAL_MOCK_METHOD_3(CIoTHubTransportMqttMocks, , void, eventConfirmationCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONFIRMATION_RESULT, result2, void*, userContextCallback); DECLARE_GLOBAL_MOCK_METHOD_3(CIoTHubTransportMqttMocks, , int, messageCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, message, void*, userContextCallback); +DECLARE_GLOBAL_MOCK_METHOD_0(CIoTHubTransportMqttMocks, , STRING_HANDLE, STRING_new); DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , STRING_HANDLE, STRING_construct, const char*, s); DECLARE_GLOBAL_MOCK_METHOD_2(CIoTHubTransportMqttMocks, , int, STRING_concat, STRING_HANDLE, s1, const char*, s2); DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , void, STRING_delete, STRING_HANDLE, s); @@ -546,26 +381,54 @@ DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , const char*, STRING_c_ DECLARE_GLOBAL_MOCK_METHOD_2(CIoTHubTransportMqttMocks, , IOTHUB_MESSAGE_HANDLE, IoTHubMessage_CreateFromByteArray, const unsigned char*, buffer, size_t, size); DECLARE_GLOBAL_MOCK_METHOD_3(CIoTHubTransportMqttMocks, , IOTHUB_MESSAGE_RESULT, IoTHubMessage_GetByteArray, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const unsigned char**, buffer, size_t*, size); DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , void, IoTHubMessage_Destroy, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle); -DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , IOTHUBMESSAGE_CONTENT_TYPE, IoTHubMessage_GetContentType, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle) +DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , IOTHUBMESSAGE_CONTENT_TYPE, IoTHubMessage_GetContentType, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle); DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , const char*, IoTHubMessage_GetString, IOTHUB_MESSAGE_HANDLE, handle); -DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , MQTTAPI_HANDLE, MQTTAPI_Create, const MQTTAPI_ConnectOptions*, options); -DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , void, MQTTAPI_Destroy, MQTTAPI_HANDLE, instance); -DECLARE_GLOBAL_MOCK_METHOD_2(CIoTHubTransportMqttMocks, , MQTTAPI_TOPIC_HANDLE, MQTTAPI_Subscribe, MQTTAPI_HANDLE, instance, const char*, topic); -DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , void, MQTTAPI_Unsubscribe, MQTTAPI_TOPIC_HANDLE, topicInstance); -DECLARE_GLOBAL_MOCK_METHOD_4(CIoTHubTransportMqttMocks, ,MQTTAPI_RESULT, MQTTAPI_PublishMessage, MQTTAPI_HANDLE, handle, const char*, topicName, const MQTTAPI_Message*, msg, void*, context); -DECLARE_GLOBAL_MOCK_METHOD_3(CIoTHubTransportMqttMocks, , MQTTAPI_RESULT, MQTTAPI_SetMessageCallback, MQTTAPI_HANDLE, instance, void*, context, MQTTAPI_MessageArrived *, ma); -DECLARE_GLOBAL_MOCK_METHOD_2(CIoTHubTransportMqttMocks, , MQTTAPI_RESULT, MQTTAPI_SetDeliveryCompletedCallback, MQTTAPI_HANDLE, instance, MQTTAPI_DeliveryComplete *, dc); -DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , void, MQTTAPI_DoWork, MQTTAPI_HANDLE, instance); +DECLARE_GLOBAL_MOCK_METHOD_4(CIoTHubTransportMqttMocks, , MQTT_CLIENT_HANDLE, mqtt_client_init, ON_MQTT_MESSAGE_RECV_CALLBACK, msgRecv, ON_MQTT_OPERATION_CALLBACK, opCallback, void*, callbackCtx, LOGGER_LOG, logger); +DECLARE_GLOBAL_MOCK_METHOD_3(CIoTHubTransportMqttMocks, , int, mqtt_client_connect, MQTT_CLIENT_HANDLE, handle, XIO_HANDLE, xioHandle, MQTT_CLIENT_OPTIONS*, mqttOptions); +DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , int, mqtt_client_disconnect, MQTT_CLIENT_HANDLE, handle); +DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , void, mqtt_client_deinit, MQTT_CLIENT_HANDLE, handle); +DECLARE_GLOBAL_MOCK_METHOD_4(CIoTHubTransportMqttMocks, , int, mqtt_client_subscribe, MQTT_CLIENT_HANDLE, handle, uint16_t, packetId, SUBSCRIBE_PAYLOAD*, subscribeList, size_t, count); +DECLARE_GLOBAL_MOCK_METHOD_4(CIoTHubTransportMqttMocks, , int, mqtt_client_unsubscribe, MQTT_CLIENT_HANDLE, handle, uint16_t, packetId, const char**, unsubscribeList, size_t, count); +DECLARE_GLOBAL_MOCK_METHOD_2(CIoTHubTransportMqttMocks, , int, mqtt_client_publish, MQTT_CLIENT_HANDLE, handle, MQTT_MESSAGE_HANDLE, msgHandle); +DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , void, mqtt_client_dowork, MQTT_CLIENT_HANDLE, handle); +DECLARE_GLOBAL_MOCK_METHOD_2(CIoTHubTransportMqttMocks, , void, mqtt_client_set_trace, MQTT_CLIENT_HANDLE, handle, bool, traceVal); +DECLARE_GLOBAL_MOCK_METHOD_5(CIoTHubTransportMqttMocks, , MQTT_MESSAGE_HANDLE, mqttmessage_create, uint16_t, packetId, const char*, topicName, QOS_VALUE, qosValue, const uint8_t*, appMsg, size_t, appMsgLength); +DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , const APP_PAYLOAD*, mqttmessage_getApplicationMsg, MQTT_MESSAGE_HANDLE, handle); +DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , void, mqttmessage_destroy, MQTT_MESSAGE_HANDLE, handle); -DECLARE_GLOBAL_MOCK_METHOD_2(CIoTHubTransportMqttMocks, , IOTHUBMESSAGE_DISPOSITION_RESULT, IoTHubClient_LL_MessageCallback, IOTHUB_CLIENT_LL_HANDLE, handle, IOTHUB_MESSAGE_HANDLE, message) -DECLARE_GLOBAL_MOCK_METHOD_3(CIoTHubTransportMqttMocks, , void, IoTHubClient_LL_SendComplete, IOTHUB_CLIENT_LL_HANDLE, handle, PDLIST_ENTRY, completed, IOTHUB_BATCHSTATE_RESULT, result2) +DECLARE_GLOBAL_MOCK_METHOD_4(CIoTHubTransportMqttMocks, , STRING_HANDLE, SASToken_Create, STRING_HANDLE, key, STRING_HANDLE, scope, STRING_HANDLE, keyName, size_t, expiry); +DECLARE_GLOBAL_MOCK_METHOD_2(CIoTHubTransportMqttMocks, , IOTHUBMESSAGE_DISPOSITION_RESULT, IoTHubClient_LL_MessageCallback, IOTHUB_CLIENT_LL_HANDLE, handle, IOTHUB_MESSAGE_HANDLE, message); +DECLARE_GLOBAL_MOCK_METHOD_3(CIoTHubTransportMqttMocks, , void, IoTHubClient_LL_SendComplete, IOTHUB_CLIENT_LL_HANDLE, handle, PDLIST_ENTRY, completed, IOTHUB_BATCHSTATE_RESULT, result2); +DECLARE_GLOBAL_MOCK_METHOD_1(CIoTHubTransportMqttMocks, , time_t, get_time, time_t*, currentTime); BEGIN_TEST_SUITE(iothubtransportmqtt) + static void SetupMocksForInitConnection(CIoTHubTransportMqttMocks& mocks) + { + STRICT_EXPECTED_CALL(mocks, get_time(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(mocks, STRING_new()); + EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)).ExpectedTimesExactly(4); +#if _WIN32 + STRICT_EXPECTED_CALL(mocks, tlsio_schannel_get_interface_description()); +#else +#ifdef MBED_BUILD_TIMESTAMP + STRICT_EXPECTED_CALL(mocks, tlsio_wolfssl_get_interface_description()); +#else + STRICT_EXPECTED_CALL(mocks, tlsio_openssl_get_interface_description()); +#endif +#endif + EXPECTED_CALL(mocks, mqtt_client_connect(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, SASToken_Create(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + + EXPECTED_CALL(mocks, xio_create(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + } + TEST_SUITE_INITIALIZE(TestClassInitialize) { INITIALIZE_MEMORY_DEBUG(g_dllByDll); @@ -595,13 +458,13 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) currentSTRING_concat_call = 0; whenShallSTRING_concat_fail = 0; - testDeliverycompletedCallBack = NULL; - contextReceivedAtPublishMessage = NULL; + g_fnMqttMsgRecv = NULL; + g_fnMqttOperationCallback = NULL; + g_callbackCtx = NULL; - BASEIMPLEMENTATION::DList_InitializeListHead(&waitingToSend); + BASEIMPLEMENTATION::DList_InitializeListHead(&g_waitingToSend); } - TEST_FUNCTION_CLEANUP(TestMethodCleanup) { if (!MicroMockReleaseMutex(g_testByTest)) @@ -610,9 +473,21 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) } } + static void SetupIothubTransportConfig(IOTHUBTRANSPORT_CONFIG* config, const char* deviceId, const char* deviceKey, const char* iotHubName, + const char* iotHubSuffix, const char* protocolGatewayHostName) + { + g_iothubClientConfig.protocol = MQTT_Protocol; + g_iothubClientConfig.deviceId = deviceId; + g_iothubClientConfig.deviceKey = deviceKey; + g_iothubClientConfig.iotHubName = iotHubName; + g_iothubClientConfig.iotHubSuffix = iotHubSuffix; + g_iothubClientConfig.protocolGatewayHostName = protocolGatewayHostName; + config->waitingToSend = &g_waitingToSend; + config->upperConfig = &g_iothubClientConfig; + } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_001: [If parameter config is NULL then IoTHubTransportMqtt_Create shall fail and return NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_parameter_fails) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_001: [If parameter config is NULL then IoTHubTransportMqtt_Create shall return NULL.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_parameter_Succeed) { ///arrange CIoTHubTransportMqttMocks mocks; @@ -626,14 +501,16 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) ///cleanup } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_001: [If parameter config is NULL then IoTHubTransportMqtt_Create shall fail and return NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [If the parameter config's variables upperConfig or waitingToSend are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_config_parameter_fails) { ///arrange CIoTHubTransportMqttMocks mocks; - + IOTHUBTRANSPORT_CONFIG config = { 0 }; + config.waitingToSend = &g_waitingToSend; + ///act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_NULL_CONFIG); + auto result = IoTHubTransportMqtt_Create(&config); ///assert ASSERT_IS_NULL(result); @@ -641,1066 +518,766 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) ///cleanup } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [If the parameter config's variables upperConfig or waitingToSend are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_waitingToSend_fails) { // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + config.waitingToSend = NULL; // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_NULL_WAITING_TO_SEND); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_009: [If any error is encountered then IoTHubTransportMqtt_Create shall return NULL.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_protocol_fails) { // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + g_iothubClientConfig.protocol = NULL; // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_NULL_PROTOCOL); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_device_id_fails) { // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, NULL, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_NULL_DEVICE_ID); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_device_key_fails) { // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, NULL, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_NULL_DEVICE_KEY); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_iothub_name_fails) { // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, NULL, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_NULL_IOTHUB_NAME); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_iothub_suffix_fails) { // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, NULL, TEST_PROTOCOL_GATEWAY_HOSTNAME); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_NULL_IOTHUB_SUFFIX); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_002: [IoTHubTransportMqtt_Create shall fail and return NULL if any fields of the config structure are NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_protocol_gateway_hostname_fails) - { - // arrange - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_NULL_PROTOCOL_GATEWAY_HOSTNAME); - - // assert - ASSERT_IS_NULL(result); - } - - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_003: [IoTHubTransportMqtt_Create shall fail and return NULL if the configuration deviceId is greater than 128 ascii characters.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_006: [If the upperConfig's variables deviceId is an empty strings or length is greater then 128 then IoTHubTransportMqtt_Create shall return NULL.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_with_very_long_device_id_fails) { // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_VERY_LONG_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_VERY_LONG_DEVICE_ID); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_013: [Otherwise, IoTHubTransportMqtt_Create shall succeed and return a non-NULL value] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_005: [Otherwise, IoTHubTransportMqtt_Create shall create an immutable string (further called Event mqttEventTopic) that will be formed by devices//messages/events.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_007: [Otherwise, IoTHubTransportMqtt_Create shall create an immutable string(further called Event mqttMessageTopic) that will be formed by devices / / messages / devicebound.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_009: [IoTHubTransportMqtt_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key, sasTokenSr and client handle shall be saved.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_011: [IoTHubTransportMqtt_Create shall call MQTTAPI_Create passing MQTTAPI_connectOptions (deviceId, deviceKey and HostAddress).] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_025: [IoTHubTransportMqtt_Create shall call MQTTAPI_SetMessageCallback and MQTTAPI_SetDeliveryCompletedCallback for message arrived and message delivered (Answer to Event).] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_happy_path_Succeed) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_007: [If the upperConfig's variables protocolGatewayHostName is non-Null and the length is an empty string then IoTHubTransportMqtt_Create shall return NULL.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Create_with_NULL_protocol_gateway_hostname_Succeeds) { // arrange CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, NULL); - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_MESSAGE_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_EVENT_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_SAS_TOKEN)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_HOST_NAME)); + EXPECTED_CALL(mocks, mqtt_client_init(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, ".")) .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, TEST_IOTHUB_SUFFIX)) .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, "/")) .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, TEST_DEVICE_ID)) .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, EVENT_ENDPOINT)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, MESSAGE_ENDPOINT)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_Create(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_SetMessageCallback(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_SetDeliveryCompletedCallback(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(NULL)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NOT_NULL(result); - mocks.AssertActualAndExpectedCalls(); // clean up IoTHubTransportMqtt_Destroy(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_004: [IoTHubTransportMqtt_Create shall fail and return NULL if the configuration parameters deviceId, deviceKey, IoTHubName and protocolGatewayHostName are an empty string in size.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_with_empty_device_id_fails) - { - // arrange - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_EMPTY_DEVICE_ID); - - // assert - ASSERT_IS_NULL(result); - - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_004: [IoTHubTransportMqtt_Create shall fail and return NULL if the configuration parameters deviceId, deviceKey, IoTHubName and protocolGatewayHostName are an empty string in size.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_with_empty_device_key_fails) - { - // arrange - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_EMPTY_DEVICE_KEY); - - // assert - ASSERT_IS_NULL(result); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_004: [IoTHubTransportMqtt_Create shall fail and return NULL if the configuration parameters deviceId, deviceKey, IoTHubName and protocolGatewayHostName are an empty string in size.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_with_empty_iothub_name_fails) - { - // arrange - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_EMPTY_IOTHUB_NAME); - - // assert - ASSERT_IS_NULL(result); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_004: [IoTHubTransportMqtt_Create shall fail and return NULL if the configuration parameters deviceId, deviceKey, IoTHubName and protocolGatewayHostName are an empty string in size.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_007: [If the upperConfig's variables protocolGatewayHostName is non-Null and the length is an empty string then IoTHubTransportMqtt_Create shall return NULL.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_with_empty_protocol_gateway_hostname_fails) { // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_EMPTY_STRING); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG_EMPTY_PROTOCOL_GATEWAY_HOSTNAME); + auto result = IoTHubTransportMqtt_Create(&config); + + // assert + ASSERT_IS_NULL(result); + + // clean up + } + + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_010: [IoTHubTransportMqtt_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key, sasTokenSr and client handle shall be saved.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_011: [On Success IoTHubTransportMqtt_Create shall return a non-NULL value.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_Succeed) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, NULL); + + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_MESSAGE_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_EVENT_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_SAS_TOKEN)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_HOST_NAME)); + + EXPECTED_CALL(mocks, mqtt_client_init(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)); + + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, ".")) + .IgnoreArgument(1); + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, TEST_IOTHUB_SUFFIX)) + .IgnoreArgument(1); + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, "/")) + .IgnoreArgument(1); + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, TEST_DEVICE_ID)) + .IgnoreArgument(1); + + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + + // act + auto result = IoTHubTransportMqtt_Create(&config); + + // assert + ASSERT_IS_NOT_NULL(result); + mocks.AssertActualAndExpectedCalls(); + + // clean up + IoTHubTransportMqtt_Destroy(result); + } + + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_008: [If the upperConfig contains a valid protocolGatewayHostName value the this shall be used for the hostname, otherwise the hostname shall be constructed using the iothubname and iothubSuffix.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_ProtocolGateway_Succeed) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_MESSAGE_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_EVENT_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_SAS_TOKEN)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); + + EXPECTED_CALL(mocks, mqtt_client_init(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, ".")) + .IgnoreArgument(1); + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, TEST_IOTHUB_SUFFIX)) + .IgnoreArgument(1); + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, "/")) + .IgnoreArgument(1); + STRICT_EXPECTED_CALL(mocks, STRING_concat(IGNORED_PTR_ARG, TEST_DEVICE_ID)) + .IgnoreArgument(1); + + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + + // act + auto result = IoTHubTransportMqtt_Create(&config); + + // assert + ASSERT_IS_NOT_NULL(result); + mocks.AssertActualAndExpectedCalls(); + + // clean up + IoTHubTransportMqtt_Destroy(result); + } + + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_009: [If any error is encountered then IoTHubTransportMqtt_Create shall return NULL.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Create_hostAddress_fails) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, NULL); + + whenShallSTRING_construct_fail = 6; + + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_MESSAGE_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_EVENT_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_SAS_TOKEN)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_HOST_NAME)); + + EXPECTED_CALL(mocks, mqtt_client_init(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + + // act + auto result = IoTHubTransportMqtt_Create(&config); + + // assert + ASSERT_IS_NULL(result); + mocks.AssertActualAndExpectedCalls(); + + // clean up + } + + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Create_with_empty_device_id_fails) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_EMPTY_STRING, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + // act + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - - /*Tests_SRS_IOTHUBTRANSPORTMQTT_04_005: [Otherwise, IoTHubTransportMqtt_Create shall create an immutable string (further called Event mqttEventTopic) that will be formed by devices//messages/events.] */ - TEST_FUNCTION(IotHubTransportMqtt_EVENT_ENDPOINT_constant_is_expected_value) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Create_with_empty_device_key_fails) { - ASSERT_ARE_EQUAL(char_ptr, "/messages/events", EVENT_ENDPOINT); + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_EMPTY_STRING, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + // act + auto result = IoTHubTransportMqtt_Create(&config); + + // assert + ASSERT_IS_NULL(result); } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_006: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransportMqtt_Create shall return NULL.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Create_with_empty_iothub_name_fails) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_EMPTY_STRING, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + // act + auto result = IoTHubTransportMqtt_Create(&config); + + // assert + ASSERT_IS_NULL(result); + } + + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_011: [On Success IoTHubTransportMqtt_Create shall return a non-NULL value.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_String_construct_fails_fail) { // arrange CIoTHubTransportMqttMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); whenShallSTRING_construct_fail = 5; - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); - // assert - ASSERT_IS_NULL(result); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_006: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_string_concat_devices_fails_fail) - { - // arrange - CIoTHubTransportMqttMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_SAS_TOKEN)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_MESSAGE_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_EVENT_TOPIC)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1) - .SetReturn((int)__LINE__); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_006: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_string_concat_deviceid_fails_fail) - { - // arrange - CIoTHubTransportMqttMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1) - .SetReturn((int)__LINE__); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); - - // assert - ASSERT_IS_NULL(result); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_006: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_string_concat_event_endpoint_fails_fail) - { - // arrange - CIoTHubTransportMqttMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, EVENT_ENDPOINT)) - .IgnoreArgument(1) - .SetReturn((int)__LINE__); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); - - // assert - ASSERT_IS_NULL(result); - } - - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_008: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_011: [On Success IoTHubTransportMqtt_Create shall return a non-NULL value.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_string_contruct_for_message_fails_fail) { // arrange CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); + whenShallSTRING_construct_fail = 4; + + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_SAS_TOKEN)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_EVENT_TOPIC)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, EVENT_ENDPOINT)) - .IgnoreArgument(1); - - whenShallSTRING_construct_fail = 6; - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_008: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_string_concat_devices_for_message_fails_fail) - { - // arrange - CIoTHubTransportMqttMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, EVENT_ENDPOINT)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1) - .SetReturn((int)__LINE__); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); - - // assert - ASSERT_IS_NULL(result); - } - - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_008: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_011: [On Success IoTHubTransportMqtt_Create shall return a non-NULL value.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_string_construct_sasTokenSr_fails_fail) { // arrange CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); + whenShallSTRING_construct_fail = 3; + + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_SAS_TOKEN)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); - whenShallSTRING_construct_fail = 4; - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - - - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_008: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_string_concat_deviceId_for_message_fails_fail) - { - // arrange - CIoTHubTransportMqttMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, EVENT_ENDPOINT)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1) - .SetReturn(__LINE__); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); - - // assert - ASSERT_IS_NULL(result); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_008: [If creating the string fail for any reason then IoTHubTransportMqtt_Create shall fail and return NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_string_concat_messageEndpoint_for_message_fails_fail) - { - // arrange - CIoTHubTransportMqttMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, EVENT_ENDPOINT)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, MESSAGE_ENDPOINT)) - .IgnoreArgument(1) - .SetReturn(__LINE__); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); - - // assert - ASSERT_IS_NULL(result); - } - - /* Tetsts_SRS_IOTHUBTRANSPORTMQTT_04_010: [If memory allocation fails IoTHubTransportMqtt_Create shall fail and return NULL.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_011: [On Success IoTHubTransportMqtt_Create shall return a non-NULL value.] */ TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_state_Allocation_fails_fail) { // arrange CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); whenShallmalloc_fail = 1; - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_012: [If MQTTAPI_Create fail, than IoTHubTransportMqtt_Create shall fail and return NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_MQTTAPI_Create_fails_fail) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_011: [On Success IoTHubTransportMqtt_Create shall return a non-NULL value.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_mqtt_client_init_Create_fails_fail) { // arrange CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_MESSAGE_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_EVENT_TOPIC)); + STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_MQTT_SAS_TOKEN)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, mqtt_client_init(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)).SetReturn((MQTT_CLIENT_HANDLE)NULL); - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, EVENT_ENDPOINT)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, MESSAGE_ENDPOINT)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_Create(IGNORED_PTR_ARG)) - .IgnoreArgument(1) - .SetReturn((MQTTAPI_HANDLE)NULL); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); + auto result = IoTHubTransportMqtt_Create(&config); // assert ASSERT_IS_NULL(result); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_026: [If MQTTAPI_SetMessageCallback or MQTTAPI_SetDeliveryCompletedCallback fail, IoTHubTransportMqtt_Create shall fail and return NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_MQTTAPI_SetMessageCallback_fails_fail) - { - // arrange - CIoTHubTransportMqttMocks mocks; - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, EVENT_ENDPOINT)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, MESSAGE_ENDPOINT)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_Create(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_SetMessageCallback(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments() - .SetReturn((MQTTAPI_RESULT)MQTTAPI_ERROR); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); - - // assert - ASSERT_IS_NULL(result); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_026: [If MQTTAPI_SetMessageCallback or MQTTAPI_SetDeliveryCompletedCallback fail, IoTHubTransportMqtt_Create shall fail and return NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Create_validConfig_MQTTAPI_SetDeliveryCompletedCallback_fails_fail) - { - // arrange - CIoTHubTransportMqttMocks mocks; - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_PROTOCOL_GATEWAY_HOSTNAME)); - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_ID)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_DEVICE_KEY)); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_IOTHUB_NAME)); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, ".")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_IOTHUB_SUFFIX)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, "/devices/")) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, EVENT_ENDPOINT)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct("devices/")); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, TEST_DEVICE_ID)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_concat(NULL, MESSAGE_ENDPOINT)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_Create(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_SetMessageCallback(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_SetDeliveryCompletedCallback(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments() - .SetReturn((MQTTAPI_RESULT)MQTTAPI_ERROR); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); - - // act - auto result = IoTHubTransportMqtt_Create(&TEST_CONFIG); - - // assert - ASSERT_IS_NULL(result); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_014: [IoTHubTransportMqtt_Destroy shall do nothing if parameter handle is NULL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Destroy_parameter_NULL_Do_Nothing) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_012: [IoTHubTransportMqtt_Destroy shall do nothing if parameter handle is NULL.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Destroy_parameter_NULL_succeed) { // arrange CIoTHubTransportMqttMocks mocks; // act IoTHubTransportMqtt_Destroy(NULL); - // assert + // assert } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_015: [Otherwise IoTHubTransportMqtt_Destroy shall free all the resources currently in use.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_013: [If the parameter subscribe is true then IoTHubTransportMqtt_Destroy shall call IoTHubTransportMqtt_Unsubscribe.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Destroy_Unsubscribe_succeeds) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); + (void)IoTHubTransportMqtt_Subscribe(handle); + CONNECT_ACK connack = { true, CONNECTION_ACCEPTED }; + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_CONNACK, &connack, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); + mocks.ResetAllCalls(); + + EXPECTED_CALL(mocks, STRING_c_str(NULL)); + + EXPECTED_CALL(mocks, DList_IsListEmpty(IGNORED_PTR_ARG)); + + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + + STRICT_EXPECTED_CALL(mocks, mqtt_client_disconnect(TEST_MQTT_CLIENT_HANDLE)); + STRICT_EXPECTED_CALL(mocks, mqtt_client_deinit(TEST_MQTT_CLIENT_HANDLE)); + STRICT_EXPECTED_CALL(mocks, mqtt_client_unsubscribe(TEST_MQTT_CLIENT_HANDLE, IGNORED_NUM_ARG, IGNORED_PTR_ARG, 1)) + .IgnoreArgument(2) + .IgnoreArgument(3); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + + // act + IoTHubTransportMqtt_Destroy(handle); + + // assert + } + + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_014: [IoTHubTransportMqtt_Destroy shall free all the resources currently in use.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Destroy_One_Message_Ack_succeeds) + { + // arrange + CIoTHubTransportMqttMocks mocks; + + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE }; + SUBSCRIBE_ACK suback; + suback.packetId = 1234; + suback.qosCount = 1; + suback.qosReturn = QosValue; + + DList_InsertTailList(config.waitingToSend, &(message1.entry)); + auto handle = IoTHubTransportMqtt_Create(&config); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); + mocks.ResetAllCalls(); + + EXPECTED_CALL(mocks, DList_IsListEmpty(IGNORED_PTR_ARG)).ExpectedTimesExactly(2); + EXPECTED_CALL(mocks, DList_RemoveHeadList(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, DList_InsertTailList(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_SendComplete(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IOTHUB_BATCHSTATE_FAILED)) + .IgnoreArgument(1) + .IgnoreArgument(2); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + + STRICT_EXPECTED_CALL(mocks, mqtt_client_disconnect(TEST_MQTT_CLIENT_HANDLE)); + STRICT_EXPECTED_CALL(mocks, mqtt_client_deinit(TEST_MQTT_CLIENT_HANDLE)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + + // act + IoTHubTransportMqtt_Destroy(handle); + + // assert + } + + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_014: [IoTHubTransportMqtt_Destroy shall free all the resources currently in use.] */ TEST_FUNCTION(IoTHubTransportMqtt_Destroy_succeeds) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, DList_IsListEmpty(IGNORED_PTR_ARG)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, DList_IsListEmpty(IGNORED_PTR_ARG)); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_delete(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, MQTTAPI_Destroy(NULL)) - .IgnoreArgument(1); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + EXPECTED_CALL(mocks, STRING_delete(NULL)); + + STRICT_EXPECTED_CALL(mocks, mqtt_client_disconnect(TEST_MQTT_CLIENT_HANDLE)); + STRICT_EXPECTED_CALL(mocks, mqtt_client_deinit(TEST_MQTT_CLIENT_HANDLE)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); // act IoTHubTransportMqtt_Destroy(handle); - // assert + // assert } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_016: [If parameter handle is NULL than IoTHubTransportMqtt_Subscribe shall fail and return a non-zero value.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Subscribe_parameter_NULL_Do_Nothing) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_015: [If parameter handle is NULL than IoTHubTransportMqtt_Subscribe shall return a non-zero value.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Subscribe_parameter_NULL_fail) { // arrange CIoTHubTransportMqttMocks mocks; // act - IoTHubTransportMqtt_Subscribe(NULL); - // assert + int res = IoTHubTransportMqtt_Subscribe(NULL); + // assert + ASSERT_ARE_NOT_EQUAL(int, 0, res); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_017: [Otherwise, IoTHubTransportMqtt_Subscribe shall call MQTTAPI_Subscribe.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_018: [If MQTTAPI_Subscribe succeeed, IoTHubTransportMqtt_Subscribe shall succeed.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Subscribe_happy_path_Succeed) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_017: [Upon failure IoTHubTransportMqtt_Subscribe shall return a non-zero value.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Subscribe_mqtt_client_subscribe_return_error_fail) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); - mocks.ResetAllCalls(); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); - STRICT_EXPECTED_CALL(mocks, MQTTAPI_Subscribe(TEST_MQTTAPI_HANDLE, TEST_MQTTAPI_MESSAGE_TOPIC)); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1) - .SetReturn((const char*)TEST_MQTTAPI_MESSAGE_TOPIC); - - // act + auto handle = IoTHubTransportMqtt_Create(&config); auto result = IoTHubTransportMqtt_Subscribe(handle); + CONNECT_ACK connack = { true, CONNECTION_ACCEPTED }; + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_CONNACK, &connack, g_callbackCtx); + + mocks.ResetAllCalls(); + + STRICT_EXPECTED_CALL(mocks, mqtt_client_subscribe(TEST_MQTT_CLIENT_HANDLE, IGNORED_NUM_ARG, IGNORED_PTR_ARG, 1)) + .IgnoreArgument(2) + .IgnoreArgument(3) + .SetReturn(__LINE__); + EXPECTED_CALL(mocks, STRING_c_str(NULL)); + STRICT_EXPECTED_CALL(mocks, mqtt_client_dowork(TEST_MQTT_CLIENT_HANDLE)); + SetupMocksForInitConnection(mocks); + + // act + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); // assert - ASSERT_ARE_EQUAL(int, 0, result); mocks.AssertActualAndExpectedCalls(); //cleanup IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_019: [Otherwise, IoTHubTransportMqtt_Subscribe shall fail and return a non - zero value.] */ - TEST_FUNCTION(IoTHubTransportMqtt_Subscribe_MQTTAPI_Subscribe_fails_fail) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_016: [IoTHubTransportMqtt_Subscribe shall call mqtt_client_subscribe to subscribe to the Message Topic.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_018: [On success IoTHubTransportMqtt_Subscribe shall return 0.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Subscribe_Succeed) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); + auto result = IoTHubTransportMqtt_Subscribe(handle); + CONNECT_ACK connack = { true, CONNECTION_ACCEPTED }; + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_CONNACK, &connack, g_callbackCtx); mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1) - .SetReturn((const char*)TEST_MQTTAPI_MESSAGE_TOPIC); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_Subscribe(TEST_MQTTAPI_HANDLE, TEST_MQTTAPI_MESSAGE_TOPIC)) - .SetReturn((MQTTAPI_TOPIC_HANDLE)NULL); - - + STRICT_EXPECTED_CALL(mocks, mqtt_client_subscribe(TEST_MQTT_CLIENT_HANDLE, IGNORED_NUM_ARG, IGNORED_PTR_ARG, 1)) + .IgnoreArgument(2) + .IgnoreArgument(3); + EXPECTED_CALL(mocks, STRING_c_str(NULL) ).SetReturn(TEST_MQTT_MESSAGE_TOPIC); + STRICT_EXPECTED_CALL(mocks, mqtt_client_dowork(TEST_MQTT_CLIENT_HANDLE) ); + SetupMocksForInitConnection(mocks); // act - IoTHubTransportMqtt_Subscribe(handle); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); // assert - //ASSERT_ARE_NOT_EQUAL(int, 0, result); mocks.AssertActualAndExpectedCalls(); //cleanup IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_020: [If parameter handle is NULL then IoTHubTransportMqtt_Unsubscribe shall do nothing.] */\ - TEST_FUNCTION(IoTHubTransportMqtt_UnSubscribe_parameter_NULL_Do_Nothing) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_019: [If parameter handle is NULL then IoTHubTransportMqtt_Unsubscribe shall do nothing.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Unsubscribe_parameter_NULL_fail) { // arrange CIoTHubTransportMqttMocks mocks; // act IoTHubTransportMqtt_Unsubscribe(NULL); - // assert + // assert } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_021: [Otherwise it shall call MQTTAPI_Unsubscribe.] */ - TEST_FUNCTION(IoTHubTransportMqtt_UnSubscribe_happyPath) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_020: [IoTHubTransportMqtt_Unsubscribe shall call mqtt_client_unsubscribe to unsubscribe the mqtt message topic.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Unsubscribe_Succeeds) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); IoTHubTransportMqtt_Subscribe(handle); + + CONNECT_ACK connack = { true, CONNECTION_ACCEPTED }; + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_CONNACK, &connack, g_callbackCtx); + + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); + mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, MQTTAPI_Unsubscribe(TEST_MQTTAPI_TOPIC_HANDLE)); - + STRICT_EXPECTED_CALL(mocks, mqtt_client_unsubscribe(TEST_MQTT_CLIENT_HANDLE, IGNORED_NUM_ARG, IGNORED_PTR_ARG, 1)) + .IgnoreArgument(2) + .IgnoreArgument(3); + EXPECTED_CALL(mocks, STRING_c_str(NULL)).SetReturn(TEST_MQTT_MESSAGE_TOPIC); + // act IoTHubTransportMqtt_Unsubscribe(handle); @@ -1711,19 +1288,24 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_038: [IoTHubTransportMqtt_SetOption shall return IOTHUB_CLIENT_ERROR , since it does not support any extra parameter today.] */ - TEST_FUNCTION(IoTHubTransportMqtt_setoption_returnerror) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_021: [If any parameter is NULL then IoTHubTransportMqtt_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Setoption_invalid_option_fail) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); mocks.ResetAllCalls(); + bool traceOn = true; + // act - auto result = IoTHubTransportMqtt_SetOption(handle, "", ""); + auto result = IoTHubTransportMqtt_SetOption(handle, "invalid", ""); // assert - ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_ERROR , result); + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); mocks.AssertActualAndExpectedCalls(); @@ -1731,8 +1313,83 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_022: [If parameter handle is NULL or parameter iotHubClientHandle then IoTHubTransportMqtt_DoWork shall immediately return.] */ - TEST_FUNCTION(IoTHubTransportMqtt_DoWork_parameter_handle_NULL_Do_Nothing) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_021: [If any parameter is NULL then IoTHubTransportMqtt_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Setoption_option_NULL_fail) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); + mocks.ResetAllCalls(); + + bool traceOn = true; + + // act + auto result = IoTHubTransportMqtt_SetOption(handle, NULL, &traceOn); + + // assert + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); + + mocks.AssertActualAndExpectedCalls(); + + //cleanup + IoTHubTransportMqtt_Destroy(handle); + } + + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_021: [If any parameter is NULL then IoTHubTransportMqtt_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Setoption_value_NULL_fail) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); + mocks.ResetAllCalls(); + + // act + auto result = IoTHubTransportMqtt_SetOption(handle, LOG_TRACE_OPTION, NULL); + + // assert + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result); + + mocks.AssertActualAndExpectedCalls(); + + //cleanup + IoTHubTransportMqtt_Destroy(handle); + } + + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_031: [If the option parameter is set to "logtrace" then the value shall be a bool_ptr and the value will determine if the mqtt client log is on or off.] */ + TEST_FUNCTION(IoTHubTransportMqtt_Setoption_succeed) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); + mocks.ResetAllCalls(); + + STRICT_EXPECTED_CALL(mocks, mqtt_client_set_trace(TEST_MQTT_CLIENT_HANDLE, IGNORED_PTR_ARG)).IgnoreArgument(2); + + bool traceOn = true; + + // act + auto result = IoTHubTransportMqtt_SetOption(handle, LOG_TRACE_OPTION, &traceOn); + + // assert + ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result); + + mocks.AssertActualAndExpectedCalls(); + + //cleanup + IoTHubTransportMqtt_Destroy(handle); + } + + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_026: [IoTHubTransportMqtt_DoWork shall do nothing if parameter handle and/or iotHubClientHandle is NULL.] */ + TEST_FUNCTION(IoTHubTransportMqtt_DoWork_parameter_handle_NULL_fail) { // arrange CIoTHubTransportMqttMocks mocks; @@ -1743,8 +1400,8 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_022: [If parameter handle is NULL or parameter iotHubClientHandle then IoTHubTransportMqtt_DoWork shall immediately return.] */ - TEST_FUNCTION(IoTHubTransportMqtt_DoWork_parameter_iothubClient_NULL_Do_Nothing) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_026: [IoTHubTransportMqtt_DoWork shall do nothing if parameter handle and/or iotHubClientHandle is NULL.] */ + TEST_FUNCTION(IoTHubTransportMqtt_DoWork_parameter_iothubClient_NULL_fail) { // arrange CIoTHubTransportMqttMocks mocks; @@ -1755,8 +1412,8 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_022: [If parameter handle is NULL or parameter iotHubClientHandle then IoTHubTransportMqtt_DoWork shall immediately return.] */ - TEST_FUNCTION(IoTHubTransportMqtt_DoWork_all_parameters_NULL_Do_Nothing) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_026: [IoTHubTransportMqtt_DoWork shall do nothing if parameter handle and/or iotHubClientHandle is NULL.] */ + TEST_FUNCTION(IoTHubTransportMqtt_DoWork_all_parameters_NULL_fail) { // arrange CIoTHubTransportMqttMocks mocks; @@ -1767,17 +1424,19 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_027: [IoTHubTransportMqtt_DoWork shall inspect the waitingToSend DLIST passed in config structure.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_028: [If the list is empty then IoTHubTransportMqtt_DoWork shall proceed to the following action.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_040: [IoTHubTransportMqtt_DoWork shall call MQTTAPI_DoWork everytime it is called, once.] */ - TEST_FUNCTION(IoTHubTransportMqtt_DoWork_happy_path_no_messages_succeed) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransportMqtt_DoWork shall inspect the waitingToSend DLIST passed in config structure.] */ + TEST_FUNCTION(IoTHubTransportMqtt_DoWork_no_messages_succeed) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, MQTTAPI_DoWork(TEST_MQTTAPI_HANDLE)); + STRICT_EXPECTED_CALL(mocks, mqtt_client_dowork(TEST_MQTT_CLIENT_HANDLE)); + SetupMocksForInitConnection(mocks); // act IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); @@ -1787,47 +1446,44 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) //cleanup IoTHubTransportMqtt_Destroy(handle); - } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_027: [IoTHubTransportMqtt_DoWork shall inspect the waitingToSend DLIST passed in config structure.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_031: [If the list has at least one entry IotHubTransportMQtt_DoWork shall call IotHubMessage_GetData to receive message content and size.]*/ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_033: [Otherwise IoTHubTransportMqtt_DoWork shall call MQTTAPI_PublishMessage.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_030: [Otherwise the message shall be removed from waitingToSend and moved to a list where it will be waiting for receiving an ACK from Mqtt server (IoTHub or ProtocolGateway)] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_040: [IoTHubTransportMqtt_DoWork shall call MQTTAPI_DoWork everytime it is called, once.] */ - TEST_FUNCTION(IoTHubTransportMqtt_DoWork_with_1_event_item_happy_path_succeeds) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransportMqtt_DoWork shall inspect the waitingToSend DLIST passed in config structure.] */ + TEST_FUNCTION(IoTHubTransportMqtt_DoWork_with_1_event_item_succeeds) { // arrange CIoTHubTransportMqttMocks mocks; - DList_InsertTailList(&(waitingToSend), &(message1.entry)); - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE }; + SUBSCRIBE_ACK suback; + suback.packetId = 1234; + suback.qosCount = 1; + suback.qosReturn = QosValue; + + DList_InsertTailList(config.waitingToSend, &(message1.entry)); + auto handle = IoTHubTransportMqtt_Create(&config); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(message1.messageHandle)); - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetByteArray(message1.messageHandle, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(TEST_IOTHUB_MSG_BYTEARRAY)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetByteArray(TEST_IOTHUB_MSG_BYTEARRAY, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) .IgnoreArgument(2) .IgnoreArgument(3); - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, DList_RemoveEntryList(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_PublishMessage(IGNORED_PTR_ARG, TEST_MQTTAPI_EVENT_TOPIC, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + STRICT_EXPECTED_CALL(mocks, mqttmessage_create(IGNORED_NUM_ARG, IGNORED_PTR_ARG, DELIVER_AT_LEAST_ONCE, appMessage, appMsgSize)) .IgnoreArgument(1) - .IgnoreArgument(3) - .IgnoreArgument(4); - + .IgnoreArgument(2); + STRICT_EXPECTED_CALL(mocks, mqtt_client_publish(TEST_MQTT_CLIENT_HANDLE, IGNORED_PTR_ARG)) + .IgnoreArgument(2); STRICT_EXPECTED_CALL(mocks, DList_InsertTailList(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) .IgnoreArgument(1) .IgnoreArgument(2); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_DoWork(TEST_MQTTAPI_HANDLE)); + STRICT_EXPECTED_CALL(mocks, mqtt_client_dowork(TEST_MQTT_CLIENT_HANDLE)); + EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, DList_RemoveEntryList(IGNORED_PTR_ARG)); // act IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); @@ -1839,43 +1495,42 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_027: [IoTHubTransportMqtt_DoWork shall inspect the waitingToSend DLIST passed in config structure.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_031: [If the list has at least one entry IotHubTransportMQtt_DoWork shall call IotHubMessage_GetData to receive message content and size.]*/ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_033: [Otherwise IoTHubTransportMqtt_DoWork shall call MQTTAPI_PublishMessage.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_030: [Otherwise the message shall be removed from waitingToSend and moved to a list where it will be waiting for receiving an ACK from Mqtt server (IoTHub or ProtocolGateway)] */ - /*Tests_SRS_IOTHUBTRANSPORTMQTT_02_001: [If the message type is IOTHUBMESSAGE_STRING then IotHubTransportMQtt_DoWork shall call IotHubMessage_GetString to receive message content and shall compute the size as strlen.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_040: [IoTHubTransportMqtt_DoWork shall call MQTTAPI_DoWork everytime it is called, once.] */ - TEST_FUNCTION(IoTHubTransportMqtt_DoWork_with_1_event_item_STRING_type_happy_path_succeeds) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransportMqtt_DoWork shall inspect the waitingToSend DLIST passed in config structure.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_029: [IoTHubTransportMqtt_DoWork shall create a MQTT_MESSAGE_HANDLE and pass this to a call to mqtt_client_publish.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_030: [IoTHubTransportMqtt_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.] */ + TEST_FUNCTION(IoTHubTransportMqtt_DoWork_with_1_event_item_STRING_type_succeeds) { // arrange CIoTHubTransportMqttMocks mocks; - DList_InsertTailList(&(waitingToSend), &(message2.entry)); - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE }; + SUBSCRIBE_ACK suback; + suback.packetId = 1234; + suback.qosCount = 1; + suback.qosReturn = QosValue; + + DList_InsertTailList(config.waitingToSend, &(message2.entry)); + auto handle = IoTHubTransportMqtt_Create(&config); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(message2.messageHandle)); - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetString(message2.messageHandle)); - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, DList_RemoveEntryList(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_PublishMessage(IGNORED_PTR_ARG, TEST_MQTTAPI_EVENT_TOPIC, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(TEST_IOTHUB_MSG_STRING)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetString(TEST_IOTHUB_MSG_STRING)); + STRICT_EXPECTED_CALL(mocks, mqttmessage_create(IGNORED_NUM_ARG, IGNORED_PTR_ARG, DELIVER_AT_LEAST_ONCE, (const uint8_t*)appMessageString, strlen(appMessageString) )) .IgnoreArgument(1) - .IgnoreArgument(3) - .IgnoreArgument(4); - + .IgnoreArgument(2); + STRICT_EXPECTED_CALL(mocks, mqtt_client_publish(TEST_MQTT_CLIENT_HANDLE, IGNORED_PTR_ARG)) + .IgnoreArgument(2); STRICT_EXPECTED_CALL(mocks, DList_InsertTailList(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) .IgnoreArgument(1) .IgnoreArgument(2); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_DoWork(TEST_MQTTAPI_HANDLE)); + STRICT_EXPECTED_CALL(mocks, mqtt_client_dowork(TEST_MQTT_CLIENT_HANDLE)); + EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, DList_RemoveEntryList(IGNORED_PTR_ARG)); // act IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); @@ -1887,25 +1542,29 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_027: [IoTHubTransportMqtt_DoWork shall inspect the waitingToSend DLIST passed in config structure.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_031: [If the list has at least one entry IotHubTransportMQtt_DoWork shall call IotHubMessage_GetData to receive message content and size.]*/ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_033: [Otherwise IoTHubTransportMqtt_DoWork shall call MQTTAPI_PublishMessage.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_030: [Otherwise the message shall be removed from waitingToSend and moved to a list where it will be waiting for receiving an ACK from Mqtt server (IoTHub or ProtocolGateway)] */ - /*Tests_SRS_IOTHUBTRANSPORTMQTT_02_001: [If the message type is IOTHUBMESSAGE_STRING then IotHubTransportMQtt_DoWork shall call IotHubMessage_GetString to receive message content and shall compute the size as strlen.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_040: [IoTHubTransportMqtt_DoWork shall call MQTTAPI_DoWork everytime it is called, once.] */ - TEST_FUNCTION(IoTHubTransportMqtt_DoWork_with_1_event_item_STRING_type_when_GetString_fails_it_fails) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_030: [IoTHubTransportMqtt_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.] */ + TEST_FUNCTION(IoTHubTransportMqtt_DoWork_GetString_fails) { // arrange CIoTHubTransportMqttMocks mocks; - DList_InsertTailList(&(waitingToSend), &(message2.entry)); - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE }; + SUBSCRIBE_ACK suback; + suback.packetId = 1234; + suback.qosCount = 1; + suback.qosReturn = QosValue; + + DList_InsertTailList(config.waitingToSend, &(message2.entry)); + auto handle = IoTHubTransportMqtt_Create(&config); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(message2.messageHandle)); - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetString(message2.messageHandle)) - .SetReturn((const char*)NULL); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_DoWork(TEST_MQTTAPI_HANDLE)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(TEST_IOTHUB_MSG_STRING)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetString(TEST_IOTHUB_MSG_STRING)).SetReturn((const char*)NULL); + STRICT_EXPECTED_CALL(mocks, mqtt_client_dowork(TEST_MQTT_CLIENT_HANDLE)); // act IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); @@ -1917,26 +1576,32 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_032: [If IoTHubMessage_GetDatafail, IoTHubTransportMqtt_DoWork shall go to the next item on the list or move to the next action.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_040: [IoTHubTransportMqtt_DoWork shall call MQTTAPI_DoWork everytime it is called, once.] */ - TEST_FUNCTION(IoTHubTransportMqtt_DoWork_with_1_event_item_GetDatafail_fail) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_030: [IoTHubTransportMqtt_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.] */ + TEST_FUNCTION(IoTHubTransportMqtt_DoWork_GetByteArray_Error_fail) { // arrange CIoTHubTransportMqttMocks mocks; - DList_InsertTailList(&(waitingToSend), &(message1.entry)); - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE }; + SUBSCRIBE_ACK suback; + suback.packetId = 1234; + suback.qosCount = 1; + suback.qosReturn = QosValue; + + DList_InsertTailList(config.waitingToSend, &(message1.entry)); + auto handle = IoTHubTransportMqtt_Create(&config); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); mocks.ResetAllCalls(); - - - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(message1.messageHandle)); - - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetByteArray(message1.messageHandle, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetByteArray(TEST_IOTHUB_MSG_BYTEARRAY, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) .IgnoreArgument(2) .IgnoreArgument(3) .SetReturn(IOTHUB_MESSAGE_ERROR); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_DoWork(TEST_MQTTAPI_HANDLE)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(TEST_IOTHUB_MSG_BYTEARRAY)); + STRICT_EXPECTED_CALL(mocks, mqtt_client_dowork(TEST_MQTT_CLIENT_HANDLE)); // act IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); @@ -1948,52 +1613,47 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_034: [If MQTTAPI_PublishMessage fails, IoTHubTransportMqtt_DoWork shall call IoTHubClient_LL_SendComplete with status of IOTHUB_BATCHSTATE_FAILED.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_040: [IoTHubTransportMqtt_DoWork shall call MQTTAPI_DoWork everytime it is called, once.] */ - TEST_FUNCTION(IoTHubTransportMqtt_DoWork_with_1_event_item_publish_message_fails_call_sendComplete) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_030: [IoTHubTransportMqtt_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.] */ + TEST_FUNCTION(IoTHubTransportMqtt_DoWork_mqtt_client_publish_fails) { // arrange CIoTHubTransportMqttMocks mocks; - DList_InsertTailList(&(waitingToSend), &(message1.entry)); - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE }; + SUBSCRIBE_ACK suback; + suback.packetId = 1234; + suback.qosCount = 1; + suback.qosReturn = QosValue; + + DList_InsertTailList(config.waitingToSend, &(message1.entry)); + auto handle = IoTHubTransportMqtt_Create(&config); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(message1.messageHandle)); - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetByteArray(message1.messageHandle, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(TEST_IOTHUB_MSG_BYTEARRAY)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetByteArray(TEST_IOTHUB_MSG_BYTEARRAY, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) .IgnoreArgument(2) .IgnoreArgument(3); - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, DList_RemoveEntryList(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(NULL)) - .IgnoreArgument(1); - - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_PublishMessage(IGNORED_PTR_ARG, TEST_MQTTAPI_EVENT_TOPIC, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + STRICT_EXPECTED_CALL(mocks, mqttmessage_create(IGNORED_NUM_ARG, IGNORED_PTR_ARG, DELIVER_AT_LEAST_ONCE, appMessage, appMsgSize)) .IgnoreArgument(1) - .IgnoreArgument(3) - .IgnoreArgument(4) - .SetReturn(MQTTAPI_ERROR); - - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - + .IgnoreArgument(2); + STRICT_EXPECTED_CALL(mocks, mqtt_client_publish(TEST_MQTT_CLIENT_HANDLE, IGNORED_PTR_ARG)) + .IgnoreArgument(2) + .SetReturn(__LINE__); + EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(mocks, DList_InsertTailList(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) .IgnoreArgument(1) .IgnoreArgument(2); - + STRICT_EXPECTED_CALL(mocks, mqtt_client_dowork(TEST_MQTT_CLIENT_HANDLE)); + EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)); + EXPECTED_CALL(mocks, DList_RemoveEntryList(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_SendComplete(TEST_IOTHUB_CLIENT_LL_HANDLE, IGNORED_PTR_ARG, IOTHUB_BATCHSTATE_FAILED)) .IgnoreArgument(2); - - STRICT_EXPECTED_CALL(mocks, gballoc_free(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, MQTTAPI_DoWork(TEST_MQTTAPI_HANDLE)); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); // act IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); @@ -2005,13 +1665,65 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_030: [IoTHubTransportMqtt_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.] */ + TEST_FUNCTION(IoTHubTransportMqtt_DoWork_mqttmessage_create_fails) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_035: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */ + QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE }; + SUBSCRIBE_ACK suback; + suback.packetId = 1234; + suback.qosCount = 1; + suback.qosReturn = QosValue; + + DList_InsertTailList(config.waitingToSend, &(message1.entry)); + auto handle = IoTHubTransportMqtt_Create(&config); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); + mocks.ResetAllCalls(); + + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetContentType(TEST_IOTHUB_MSG_BYTEARRAY)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_GetByteArray(TEST_IOTHUB_MSG_BYTEARRAY, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .IgnoreArgument(2) + .IgnoreArgument(3); + STRICT_EXPECTED_CALL(mocks, mqttmessage_create(IGNORED_NUM_ARG, IGNORED_PTR_ARG, DELIVER_AT_LEAST_ONCE, appMessage, appMsgSize)) + .IgnoreArgument(1) + .IgnoreArgument(2) + .SetReturn( (MQTT_MESSAGE_HANDLE)NULL); + EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(mocks, DList_InsertTailList(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) + .IgnoreArgument(1) + .IgnoreArgument(2); + STRICT_EXPECTED_CALL(mocks, mqtt_client_dowork(TEST_MQTT_CLIENT_HANDLE)); + EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)); + STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_SendComplete(TEST_IOTHUB_CLIENT_LL_HANDLE, IGNORED_PTR_ARG, IOTHUB_BATCHSTATE_FAILED)) + .IgnoreArgument(2); + EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)); + EXPECTED_CALL(mocks, gballoc_free(NULL)); + //SetupMocksForInitConnection(mocks); + + // act + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); + + //assert + mocks.AssertActualAndExpectedCalls(); + + //cleanup + IoTHubTransportMqtt_Destroy(handle); + } + + /* Test_SRS_IOTHUB_MQTT_TRANSPORT_07_023: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */ TEST_FUNCTION(IoTHubTransportMqtt_GetSendStatus_InvalidHandleArgument_fail) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); mocks.ResetAllCalls(); IOTHUB_CLIENT_STATUS status; @@ -2028,12 +1740,15 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_035: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */ + /* Test_SRS_IOTHUB_MQTT_TRANSPORT_07_023: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */ TEST_FUNCTION(IoTHubTransportMqtt_GetSendStatus_InvalidStatusArgument_fail) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); mocks.ResetAllCalls(); // act @@ -2048,16 +1763,19 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_036: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_024: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.] */ TEST_FUNCTION(IoTHubTransportMqtt_GetSendStatus_empty_waitingToSend_and_empty_waitingforAck_success) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, DList_IsListEmpty(&waitingToSend)); - STRICT_EXPECTED_CALL(mocks, DList_IsListEmpty(IGNORED_PTR_ARG)).IgnoreArgument(1); + STRICT_EXPECTED_CALL(mocks, DList_IsListEmpty(config.waitingToSend) ); + STRICT_EXPECTED_CALL(mocks, DList_IsListEmpty(IGNORED_PTR_ARG) ).IgnoreArgument(1); IOTHUB_CLIENT_STATUS status; @@ -2074,21 +1792,24 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_037: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.] */ + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_025: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.] */ TEST_FUNCTION(IoTHubTransportMqtt_GetSendStatus_waitingToSend_not_empty_success) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); IOTHUB_MESSAGE_HANDLE eventMessageHandle = IoTHubMessage_CreateFromByteArray(IGNORED_PTR_ARG, IGNORED_NUM_ARG); IOTHUB_MESSAGE_LIST newEntry; newEntry.messageHandle = &newEntry; - DList_InsertTailList(&(waitingToSend), &(newEntry.entry)); + DList_InsertTailList(config.waitingToSend, &(newEntry.entry)); mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, DList_IsListEmpty(&waitingToSend)); + STRICT_EXPECTED_CALL(mocks, DList_IsListEmpty(config.waitingToSend) ); IOTHUB_CLIENT_STATUS status; @@ -2106,8 +1827,13 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubMessage_Destroy(eventMessageHandle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_039: [This function shall return a pointer to a structure of type TRANSPORT_PROVIDER having the following values for its fields:] */ - TEST_FUNCTION(MQTT_Protocol_succeeds) + /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_022: [This function shall return a pointer to a structure of type TRANSPORT_PROVIDER having the following values for its fields: IoTHubTransport_Create = IoTHubTransportMqtt_Create + IoTHubTransport_Destroy = IoTHubTransportMqtt_Destroy + IoTHubTransport_Subscribe = IoTHubTransportMqtt_Subscribe + IoTHubTransport_Unsubscribe = IoTHubTransportMqtt_Unsubscribe + IoTHubTransport_DoWork = IoTHubTransportMqtt_DoWork + IoTHubTransport_SetOption = IoTHubTransportMqtt_SetOption] */ + TEST_FUNCTION(IoTHubTransportMqtt_Protocol_succeeds) { ///arrange @@ -2127,17 +1853,22 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) ///cleanup } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_045: [If context is NULL, IoTHubTransportMqtt delivery completed callback shall do nothing.] */ TEST_FUNCTION(IoTHubTransportMqtt_delivered_NULL_context_do_Nothing) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); mocks.ResetAllCalls(); + STRICT_EXPECTED_CALL(mocks, mqtt_client_disconnect(TEST_MQTT_CLIENT_HANDLE)); + // act - testDeliverycompletedCallBack(NULL, MQTTAPI_CONFIRMATION_ERROR); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_ERROR, NULL, g_callbackCtx); + // assert mocks.AssertActualAndExpectedCalls(); @@ -2145,15 +1876,26 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_041: [IoTHubTransportMqtt shall search for the message received on context parameter to identify the message.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_042: [Once identified, IoTHubTransportMqtt shall remove the message from the WaitingforAck List.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_043: [If result IoTHubTransportMqtt is MQTTAPI_CONFIRMATION_OK IoTHubTransportMqtt shall call IoTHubClient_LL_SendComplete passing the message and status IOTHUB_BATCHSTATE_SUCCESS.] */ - TEST_FUNCTION(IoTHubTransportMqtt_delivered_with_1_event_item_happy_path_succeeds) + TEST_FUNCTION(IoTHubTransportMqtt_MqttOpCompleteCallback_PUBLISH_ACK_succeed) { // arrange CIoTHubTransportMqttMocks mocks; - DList_InsertTailList(&(waitingToSend), &(message1.entry)); - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + PUBLISH_ACK puback; + puback.packetId = 1; + + QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE }; + SUBSCRIBE_ACK suback; + suback.packetId = 1234; + suback.qosCount = 1; + suback.qosReturn = QosValue; + + DList_InsertTailList(config.waitingToSend, &(message1.entry)); + auto handle = IoTHubTransportMqtt_Create(&config); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); mocks.ResetAllCalls(); @@ -2169,7 +1911,7 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) .IgnoreArgument(1); // act - testDeliverycompletedCallBack(contextReceivedAtPublishMessage, MQTTAPI_CONFIRMATION_OK); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_PUBLISH_ACK, &puback, g_callbackCtx); //assert mocks.AssertActualAndExpectedCalls(); @@ -2178,241 +1920,196 @@ BEGIN_TEST_SUITE(iothubtransportmqtt) IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_044: [Otherwise, IoTHubTransportMqtt shall call IoTHubClient_LL_SendComplete passing the message and status IOTHUB_BATCHSTATE_FAIL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_delivered_with_1_event_item_MQTTAPI_CONFIRMATATION_ERROR_batchstate_failed) + TEST_FUNCTION(IoTHubTransportMqtt_MessageRecv_message_NULL_fail) { // arrange CIoTHubTransportMqttMocks mocks; - DList_InsertTailList(&(waitingToSend), &(message1.entry)); - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); + + mocks.ResetAllCalls(); + + // act + ASSERT_IS_NOT_NULL((void*)g_fnMqttMsgRecv); + g_fnMqttMsgRecv(NULL, g_callbackCtx); + + // assert + mocks.AssertActualAndExpectedCalls(); + + //cleanup + IoTHubTransportMqtt_Destroy(handle); + } + + TEST_FUNCTION(IoTHubTransportMqtt_MessageRecv_context_NULL_fail) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); + + mocks.ResetAllCalls(); + + // act + ASSERT_IS_NOT_NULL((void*)g_fnMqttMsgRecv); + g_fnMqttMsgRecv(TEST_MQTT_MESSAGE_HANDLE, NULL); + + // assert + mocks.AssertActualAndExpectedCalls(); + + //cleanup + IoTHubTransportMqtt_Destroy(handle); + } + + TEST_FUNCTION(IoTHubTransportMqtt_MessageRecv_Message_context_NULL_fail) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); + + mocks.ResetAllCalls(); + + // act + ASSERT_IS_NOT_NULL((void*)g_fnMqttMsgRecv); + g_fnMqttMsgRecv(NULL, NULL); + + // assert + mocks.AssertActualAndExpectedCalls(); + + //cleanup + IoTHubTransportMqtt_Destroy(handle); + } + + TEST_FUNCTION(IoTHubTransportMqtt_MessageRecv_succeed) + { + // arrange + CIoTHubTransportMqttMocks mocks; + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); mocks.ResetAllCalls(); - STRICT_EXPECTED_CALL(mocks, DList_RemoveEntryList(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, DList_InsertHeadList(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_SendComplete(TEST_IOTHUB_CLIENT_LL_HANDLE, IGNORED_PTR_ARG, IOTHUB_BATCHSTATE_FAILED)) - .IgnoreArgument(2); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); + STRICT_EXPECTED_CALL(mocks, mqttmessage_getApplicationMsg(TEST_MQTT_MESSAGE_HANDLE) ); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_CreateFromByteArray(appMessage, appMsgSize) ); + STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_MessageCallback(TEST_IOTHUB_CLIENT_LL_HANDLE, TEST_IOTHUB_MSG_BYTEARRAY)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_Destroy(TEST_IOTHUB_MSG_BYTEARRAY)); // act - testDeliverycompletedCallBack(contextReceivedAtPublishMessage, MQTTAPI_CONFIRMATION_ERROR); - - //assert - mocks.AssertActualAndExpectedCalls(); - - //cleanup - IoTHubTransportMqtt_Destroy(handle); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_044: [Otherwise, IoTHubTransportMqtt shall call IoTHubClient_LL_SendComplete passing the message and status IOTHUB_BATCHSTATE_FAIL.] */ - TEST_FUNCTION(IoTHubTransportMqtt_delivered_with_1_event_item_MQTTAPI_CONFIRMATATION_BECAUSE_DESTROY_batchstate_failed) - { - // arrange - CIoTHubTransportMqttMocks mocks; - DList_InsertTailList(&(waitingToSend), &(message1.entry)); - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); - IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); - mocks.ResetAllCalls(); - - STRICT_EXPECTED_CALL(mocks, DList_RemoveEntryList(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, DList_InsertHeadList(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_SendComplete(TEST_IOTHUB_CLIENT_LL_HANDLE, IGNORED_PTR_ARG, IOTHUB_BATCHSTATE_FAILED)) - .IgnoreArgument(2); - STRICT_EXPECTED_CALL(mocks, gballoc_free(NULL)) - .IgnoreArgument(1); - - // act - testDeliverycompletedCallBack(contextReceivedAtPublishMessage, MQTTAPI_CONFIRMATION_BECAUSE_DESTROY); - - //assert - mocks.AssertActualAndExpectedCalls(); - - //cleanup - IoTHubTransportMqtt_Destroy(handle); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_046: [If IoTHubTransportMqtt receives a call to MQTTAPI_MessageArrived with message parameter or context NULL, it shall return false] */ - TEST_FUNCTION(IoTHubTransportMqtt_messageArrived_NULL_message_return_false) - { - // arrange - CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); - - mocks.ResetAllCalls(); - - // act - auto result = testMessageArrivedCallback(contextMessageArrived, NULL); - // assert - ASSERT_IS_FALSE(result); - - mocks.AssertActualAndExpectedCalls(); - - //cleanup - IoTHubTransportMqtt_Destroy(handle); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_046: [If IoTHubTransportMqtt receives a call to MQTTAPI_MessageArrived with message parameter or context NULL, it shall return false] */ - TEST_FUNCTION(IoTHubTransportMqtt_messageArrived_NULL_contex_return_false) - { - // arrange - CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); - - mocks.ResetAllCalls(); - - MQTTAPI_Message testMessage; - testMessage.payload = buffer1; - testMessage.payloadlen = buffer1_size; - - // act - auto result = testMessageArrivedCallback(NULL, &testMessage); - // assert - ASSERT_IS_FALSE(result); - - mocks.AssertActualAndExpectedCalls(); - - //cleanup - IoTHubTransportMqtt_Destroy(handle); - } - - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_047: [IotHubTransportMqtt shall Create an IoTHubMessage by calling IoTHubMessage_create when MQTTAPI_MessageArrived is called.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_051: [IoTHubTransportMqtt shall call IoTHubClient_LL_MessageCallback.] */ - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_053: [Otherwise it shall return true.] */ - TEST_FUNCTION(IoTHubTransportMqtt_messageArrived_happypath_return_true) - { - // arrange - CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); - IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); - mocks.ResetAllCalls(); - - MQTTAPI_Message testMessage; - testMessage.payload = buffer1; - testMessage.payloadlen = buffer1_size; - - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_CreateFromByteArray(buffer1, buffer1_size)); - - STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_MessageCallback(TEST_IOTHUB_CLIENT_LL_HANDLE, IGNORED_PTR_ARG)) - .IgnoreArgument(2); - - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_Destroy(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - // act - auto result = testMessageArrivedCallback(contextMessageArrived, &testMessage); + ASSERT_IS_NOT_NULL((void*)g_fnMqttMsgRecv); + g_fnMqttMsgRecv(TEST_MQTT_MESSAGE_HANDLE, g_callbackCtx); // assert - ASSERT_IS_TRUE(result); - mocks.AssertActualAndExpectedCalls(); //cleanup IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_048: [If the call to IoTHubMessage_CreateFromByteArray fails, IoTHubTransportMqtt message arrived shall return false.] */ - TEST_FUNCTION(IoTHubTransportMqtt_messageArrived_CreateIotHubMessageFail_return_false) + TEST_FUNCTION(IoTHubTransportMqtt_MessageRecv_CreateIotHubMessage_Fail) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + auto handle = IoTHubTransportMqtt_Create(&config); mocks.ResetAllCalls(); - MQTTAPI_Message testMessage; - testMessage.payload = buffer1; - testMessage.payloadlen = buffer1_size; - - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_CreateFromByteArray(buffer1, buffer1_size)) + STRICT_EXPECTED_CALL(mocks, mqttmessage_getApplicationMsg(TEST_MQTT_MESSAGE_HANDLE)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_CreateFromByteArray(appMessage, appMsgSize)) .SetReturn((IOTHUB_MESSAGE_HANDLE)NULL); // act - auto result = testMessageArrivedCallback(contextMessageArrived, &testMessage); + ASSERT_IS_NOT_NULL((void*)g_fnMqttMsgRecv); + g_fnMqttMsgRecv(TEST_MQTT_MESSAGE_HANDLE, g_callbackCtx); // assert - ASSERT_IS_FALSE(result); - mocks.AssertActualAndExpectedCalls(); //cleanup IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_052: [If this calls fails, it shall return false] */ - TEST_FUNCTION(IoTHubTransportMqtt_messageArrived_messagecallback_ABANDONED_return_false) + TEST_FUNCTION(IoTHubTransportMqtt_MessageRecv_messagecallback_ABANDONED_fail) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE }; + SUBSCRIBE_ACK suback; + suback.packetId = 1234; + suback.qosCount = 1; + suback.qosReturn = QosValue; + + DList_InsertTailList(config.waitingToSend, &(message1.entry)); + auto handle = IoTHubTransportMqtt_Create(&config); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); mocks.ResetAllCalls(); - MQTTAPI_Message testMessage; - testMessage.payload = buffer1; - testMessage.payloadlen = buffer1_size; - - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_CreateFromByteArray(buffer1, buffer1_size)); - - STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_MessageCallback(TEST_IOTHUB_CLIENT_LL_HANDLE, IGNORED_PTR_ARG)) - .IgnoreArgument(2) + STRICT_EXPECTED_CALL(mocks, mqttmessage_getApplicationMsg(TEST_MQTT_MESSAGE_HANDLE)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_CreateFromByteArray(appMessage, appMsgSize)); + STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_MessageCallback(TEST_IOTHUB_CLIENT_LL_HANDLE, TEST_IOTHUB_MSG_BYTEARRAY)) .SetReturn((IOTHUBMESSAGE_DISPOSITION_RESULT)IOTHUBMESSAGE_ABANDONED); - - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_Destroy(IGNORED_PTR_ARG)) - .IgnoreArgument(1); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_Destroy(TEST_IOTHUB_MSG_BYTEARRAY)); // act - auto result = testMessageArrivedCallback(contextMessageArrived, &testMessage); + ASSERT_IS_NOT_NULL((void*)g_fnMqttMsgRecv); + g_fnMqttMsgRecv(TEST_MQTT_MESSAGE_HANDLE, g_callbackCtx); // assert - ASSERT_IS_FALSE(result); - mocks.AssertActualAndExpectedCalls(); //cleanup IoTHubTransportMqtt_Destroy(handle); } - /* Tests_SRS_IOTHUBTRANSPORTMQTT_04_052: [If this calls fails, it shall return false] */ - TEST_FUNCTION(IoTHubTransportMqtt_messageArrived_messagecallback_REJECTED_return_false) + TEST_FUNCTION(IoTHubTransportMqtt_MessageRecv_messagecallback_REJECTED_fail) { // arrange CIoTHubTransportMqttMocks mocks; - auto handle = IoTHubTransportMqtt_Create(&TEST_CONFIG); + IOTHUBTRANSPORT_CONFIG config = { 0 }; + SetupIothubTransportConfig(&config, TEST_DEVICE_ID, TEST_DEVICE_KEY, TEST_IOTHUB_NAME, TEST_IOTHUB_SUFFIX, TEST_PROTOCOL_GATEWAY_HOSTNAME); + + QOS_VALUE QosValue[] = { DELIVER_AT_LEAST_ONCE }; + SUBSCRIBE_ACK suback; + suback.packetId = 1234; + suback.qosCount = 1; + suback.qosReturn = QosValue; + + DList_InsertTailList(config.waitingToSend, &(message1.entry)); + auto handle = IoTHubTransportMqtt_Create(&config); + g_fnMqttOperationCallback(TEST_MQTT_CLIENT_HANDLE, MQTT_CLIENT_ON_SUBSCRIBE_ACK, &suback, g_callbackCtx); + IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); IoTHubTransportMqtt_DoWork(handle, TEST_IOTHUB_CLIENT_LL_HANDLE); mocks.ResetAllCalls(); - MQTTAPI_Message testMessage; - testMessage.payload = buffer1; - testMessage.payloadlen = buffer1_size; - - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_CreateFromByteArray(buffer1, buffer1_size)); - - STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_MessageCallback(TEST_IOTHUB_CLIENT_LL_HANDLE, IGNORED_PTR_ARG)) - .IgnoreArgument(2) + STRICT_EXPECTED_CALL(mocks, mqttmessage_getApplicationMsg(TEST_MQTT_MESSAGE_HANDLE)); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_CreateFromByteArray(appMessage, appMsgSize)); + STRICT_EXPECTED_CALL(mocks, IoTHubClient_LL_MessageCallback(TEST_IOTHUB_CLIENT_LL_HANDLE, TEST_IOTHUB_MSG_BYTEARRAY)) .SetReturn((IOTHUBMESSAGE_DISPOSITION_RESULT)IOTHUBMESSAGE_REJECTED); - - STRICT_EXPECTED_CALL(mocks, IoTHubMessage_Destroy(IGNORED_PTR_ARG)) - .IgnoreArgument(1); + STRICT_EXPECTED_CALL(mocks, IoTHubMessage_Destroy(TEST_IOTHUB_MSG_BYTEARRAY)); // act - auto result = testMessageArrivedCallback(contextMessageArrived, &testMessage); + ASSERT_IS_NOT_NULL( (void*)g_fnMqttMsgRecv); + g_fnMqttMsgRecv(TEST_MQTT_MESSAGE_HANDLE, g_callbackCtx); // assert - ASSERT_IS_FALSE(result); - mocks.AssertActualAndExpectedCalls(); //cleanup IoTHubTransportMqtt_Destroy(handle); } END_TEST_SUITE(iothubtransportmqtt) - diff --git a/c/iothub_client/tests/mqttapi_paho_unittests/CMakeLists.txt b/c/iothub_client/tests/mqttapi_paho_unittests/CMakeLists.txt deleted file mode 100644 index b99952d8..00000000 --- a/c/iothub_client/tests/mqttapi_paho_unittests/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -#Copyright (c) Microsoft. All rights reserved. -#Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#this is CMakeLists.txt for mqttapi_paho_unittests -cmake_minimum_required(VERSION 2.8.11) - -if(NOT ${use_mqtt}) - message(FATAL_ERROR "mqttapi_paho_unittests being generated without mqtt support") -endif() - - -compileAsC99() -set(theseTestsName mqttapi_paho_unittests) - -set(${theseTestsName}_cpp_files -${theseTestsName}.cpp -) - -set(${theseTestsName}_c_files -../../adapters/mqttapi_paho.c -) - -set(${theseTestsName}_h_files -) - -build_test_artifacts(${theseTestsName} ON) \ No newline at end of file diff --git a/c/iothub_client/tests/mqttapi_paho_unittests/main.c b/c/iothub_client/tests/mqttapi_paho_unittests/main.c deleted file mode 100644 index e118dcb2..00000000 --- a/c/iothub_client/tests/mqttapi_paho_unittests/main.c +++ /dev/null @@ -1,28 +0,0 @@ -/* -Microsoft Azure IoT Client Libraries -Copyright (c) Microsoft Corporation -All rights reserved. -MIT License -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -documentation files (the Software), to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - -*/ - -#include "testrunnerswitcher.h" - -int main(void) -{ - size_t failedTestCount = 0; - RUN_TEST_SUITE(mqttapi_paho_unittests, failedTestCount); - return failedTestCount; -} diff --git a/c/iothub_client/tests/mqttapi_paho_unittests/mqttapi_paho_unittests.cpp b/c/iothub_client/tests/mqttapi_paho_unittests/mqttapi_paho_unittests.cpp deleted file mode 100644 index dfe486bc..00000000 --- a/c/iothub_client/tests/mqttapi_paho_unittests/mqttapi_paho_unittests.cpp +++ /dev/null @@ -1,888 +0,0 @@ -/* -Microsoft Azure IoT Client Libraries -Copyright (c) Microsoft Corporation -All rights reserved. -MIT License -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -documentation files (the Software), to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. -*/ - -#include -#ifdef _CRTDBG_MAP_ALLOC -#include -#endif - -#include "testrunnerswitcher.h" -#include "micromock.h" -#include "micromockcharstararenullterminatedstrings.h" -/*the below is a horrible hack*/ -#include "macro_utils.h" -#undef DEFINE_ENUM -#define DEFINE_ENUM(enumName, ...) typedef enum C2(enumName, _TAG) { FOR_EACH_1(DEFINE_ENUMERATION_CONSTANT, __VA_ARGS__)} enumName; - -#include "map.h" -#include "mqttapi.h" -#include "lock.h" -#include "strings.h" -#include "crt_abstractions.h" -#include "vector.h" -#include "MQTTClient.h" -#include "doublylinkedlist.h" -#include "sastoken.h" -#include "agenttime.h" - - -DEFINE_MICROMOCK_ENUM_TO_STRING(MQTTAPI_RESULT, MQTTAPI_RESULT_VALUES); - -#define GBALLOC_H - -extern "C" int gballoc_init(void); -extern "C" void gballoc_deinit(void); -extern "C" void* gballoc_malloc(size_t size); -extern "C" void* gballoc_calloc(size_t nmemb, size_t size); -extern "C" void* gballoc_realloc(void* ptr, size_t size); -extern "C" void gballoc_free(void* ptr); - - -namespace BASEIMPLEMENTATION -{ - /*if malloc is defined as gballoc_malloc at this moment, there'd be serious trouble*/ -#define Lock(x) (LOCK_OK + gballocState - gballocState) /*compiler warning about constant in if condition*/ -#define Unlock(x) (LOCK_OK + gballocState - gballocState) -#define Lock_Init() (LOCK_HANDLE)0x42 -#define Lock_Deinit(x) (LOCK_OK + gballocState - gballocState) -#include "gballoc.c" -#undef Lock -#undef Unlock -#undef Lock_Init -#undef Lock_Deinit - -#include "strings.c" -#include "buffer.c" -#include "vector.c" -#include "doublylinkedlist.c" -}; - -static size_t currentmalloc_call; -static size_t whenShallmalloc_fail; - -static size_t currentrealloc_call; -static size_t whenShallrealloc_fail; - -/*different STRING constructors*/ -static size_t currentSTRING_new_call; -static size_t whenShallSTRING_new_fail; - -static size_t currentSTRING_clone_call; -static size_t whenShallSTRING_clone_fail; - -static size_t currentSTRING_construct_call; -static size_t whenShallSTRING_construct_fail; - -static size_t currentSTRING_concat_call; -static size_t whenShallSTRING_concat_fail; - -static size_t currentSTRING_empty_call; -static size_t whenShallSTRING_empty_fail; - -static size_t currentSTRING_concat_with_STRING_call; -static size_t whenShallSTRING_concat_with_STRING_fail; - - -//CONSTANTS -#define TEST_DEVICE_ID "thisIsDeviceId" -#define TEST_DEVICE_KEY "thisIsDeviceKey" -#define TEST_SASTOKEN_SR "thisIsIotHubName.thisIsIoTHubNameSuffix\\Devices\\thisIsDeviceId" -#define TEST_IOTHUB_NAME "thisIsIotHubName" -#define TEST_LOCK_HANDLE (LOCK_HANDLE)0x4443 - - -//Configuration Variations -static const MQTTAPI_ConnectOptions TEST_CONFIG_MQTTAPIconnectionOptions = -{ - TEST_DEVICE_ID,/*const char* deviceId; */ - TEST_DEVICE_KEY,/*const char* deviceKey; */ - TEST_SASTOKEN_SR, /*const char* sasTokenSr; */ - TEST_IOTHUB_NAME,/*const char* serverURI; */ -}; - - -//DEFINE HERE ALL OUR CONSTANTS - -TYPED_MOCK_CLASS(CMQTTAPIMocks, CGlobalMock) -{ -public: - - /* Lock mocks */ - MOCK_STATIC_METHOD_0(, LOCK_HANDLE, Lock_Init) - MOCK_METHOD_END(LOCK_HANDLE, TEST_LOCK_HANDLE) - - MOCK_STATIC_METHOD_1(, LOCK_RESULT, Lock, LOCK_HANDLE, handle) - MOCK_METHOD_END(LOCK_RESULT, LOCK_OK) - - MOCK_STATIC_METHOD_1(, LOCK_RESULT, Unlock, LOCK_HANDLE, handle) - MOCK_METHOD_END(LOCK_RESULT, LOCK_OK) - - MOCK_STATIC_METHOD_1(, LOCK_RESULT, Lock_Deinit, LOCK_HANDLE, handle) - MOCK_METHOD_END(LOCK_RESULT, LOCK_OK) - - - - MOCK_STATIC_METHOD_1(, void*, gballoc_malloc, size_t, size) - void* result2; - currentmalloc_call++; - if (whenShallmalloc_fail>0) - { - if (currentmalloc_call == whenShallmalloc_fail) - { - result2 = (STRING_HANDLE)NULL; - } - else - { - result2 = BASEIMPLEMENTATION::gballoc_malloc(size); - } - } - else - { - result2 = BASEIMPLEMENTATION::gballoc_malloc(size); - } - MOCK_METHOD_END(void*, result2); - - MOCK_STATIC_METHOD_2(, void*, gballoc_realloc, void*, ptr, size_t, size) - void* result2; - currentrealloc_call++; - if (whenShallrealloc_fail>0) - { - if (currentrealloc_call == whenShallrealloc_fail) - { - result2 = (STRING_HANDLE)NULL; - } - else - { - result2 = BASEIMPLEMENTATION::gballoc_realloc(ptr,size); - } - } - else - { - result2 = BASEIMPLEMENTATION::gballoc_realloc(ptr, size); - } - MOCK_METHOD_END(void*,result2); - - MOCK_STATIC_METHOD_1(, void, gballoc_free, void*, ptr) - BASEIMPLEMENTATION::gballoc_free(ptr); - MOCK_VOID_METHOD_END() - - /*Strings*/ - MOCK_STATIC_METHOD_0(, STRING_HANDLE, STRING_new) - STRING_HANDLE result2; - currentSTRING_new_call++; - if (whenShallSTRING_new_fail > 0) - { - if (currentSTRING_new_call == whenShallSTRING_new_fail) - { - result2 = (STRING_HANDLE)NULL; - } - else - { - result2 = BASEIMPLEMENTATION::STRING_new(); - } - } - else - { - result2 = BASEIMPLEMENTATION::STRING_new(); - } - MOCK_METHOD_END(STRING_HANDLE, result2) - - MOCK_STATIC_METHOD_1(, STRING_HANDLE, STRING_clone, STRING_HANDLE, handle) - STRING_HANDLE result2; - currentSTRING_clone_call++; - if (whenShallSTRING_clone_fail > 0) - { - if (currentSTRING_clone_call == whenShallSTRING_clone_fail) - { - result2 = (STRING_HANDLE)NULL; - } - else - { - result2 = BASEIMPLEMENTATION::STRING_clone(handle); - } - } - else - { - result2 = BASEIMPLEMENTATION::STRING_clone(handle); - } - MOCK_METHOD_END(STRING_HANDLE, result2) - - MOCK_STATIC_METHOD_1(, STRING_HANDLE, STRING_construct, const char*, source) - STRING_HANDLE result2; - currentSTRING_construct_call++; - if (whenShallSTRING_construct_fail > 0) - { - if (currentSTRING_construct_call == whenShallSTRING_construct_fail) - { - result2 = (STRING_HANDLE)NULL; - } - else - { - result2 = BASEIMPLEMENTATION::STRING_construct(source); - } - } - else - { - result2 = BASEIMPLEMENTATION::STRING_construct(source); - } - MOCK_METHOD_END(STRING_HANDLE, result2) - - MOCK_STATIC_METHOD_1(, void, STRING_delete, STRING_HANDLE, s) - BASEIMPLEMENTATION::STRING_delete(s); - MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_2(, int, STRING_concat, STRING_HANDLE, s1, const char*, s2) - currentSTRING_concat_call++; - MOCK_METHOD_END(int, (((whenShallSTRING_concat_fail > 0) && (currentSTRING_concat_call == whenShallSTRING_concat_fail)) ? __LINE__ : BASEIMPLEMENTATION::STRING_concat(s1, s2))); - - MOCK_STATIC_METHOD_2(, int, STRING_concat_with_STRING, STRING_HANDLE, s1, STRING_HANDLE, s2) - currentSTRING_concat_with_STRING_call++; - MOCK_METHOD_END(int, (((currentSTRING_concat_with_STRING_call > 0) && (currentSTRING_concat_with_STRING_call == whenShallSTRING_concat_with_STRING_fail)) ? __LINE__ : BASEIMPLEMENTATION::STRING_concat_with_STRING(s1, s2))); - - MOCK_STATIC_METHOD_1(, int, STRING_empty, STRING_HANDLE, s) - currentSTRING_concat_call++; - MOCK_METHOD_END(int, BASEIMPLEMENTATION::STRING_empty(s)); - - MOCK_STATIC_METHOD_1(, const char*, STRING_c_str, STRING_HANDLE, s) - MOCK_METHOD_END(const char*, BASEIMPLEMENTATION::STRING_c_str(s)) - - //MQTTClient STubs - - MOCK_STATIC_METHOD_5(, int, MQTTClient_setCallbacks, MQTTClient, handle, void*, context, MQTTClient_connectionLost*, cl, MQTTClient_messageArrived*, ma, MQTTClient_deliveryComplete*, dc) - MOCK_METHOD_END(int, MQTTCLIENT_SUCCESS) - - - MOCK_STATIC_METHOD_5(, int, MQTTClient_create,MQTTClient*, handle, const char*, serverURI, const char*, clientId, int, persistence_type, void*, persistence_context) - MOCK_METHOD_END(int, MQTTCLIENT_SUCCESS) - - - MOCK_STATIC_METHOD_2(, int, MQTTClient_connect, MQTTClient, handle, MQTTClient_connectOptions*, options) - MOCK_METHOD_END(int, MQTTCLIENT_SUCCESS) - - MOCK_STATIC_METHOD_1(, void, MQTTClient_free, void*, ptr) - MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_2(, int, MQTTClient_disconnect, MQTTClient, handle, int, timeout) - MOCK_METHOD_END(int, MQTTCLIENT_SUCCESS) - - MOCK_STATIC_METHOD_1(, void, MQTTClient_destroy, MQTTClient*, handle) - MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_3(, int, MQTTClient_subscribe,MQTTClient, handle, const char*, topic, int, qos) - MOCK_METHOD_END(int, MQTTCLIENT_SUCCESS) - - MOCK_STATIC_METHOD_2(, int, MQTTClient_unsubscribe,MQTTClient, handle, const char*, topic) - MOCK_METHOD_END(int, MQTTCLIENT_SUCCESS) - - MOCK_STATIC_METHOD_1(, void, MQTTClient_freeMessage, MQTTClient_message**, msg) - MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_4(, int, MQTTClient_publishMessage,MQTTClient, handle, const char*, topicName, MQTTClient_message*, msg, MQTTClient_deliveryToken*, dt) - MOCK_METHOD_END(int, MQTTCLIENT_SUCCESS) - - - /* DoublyLinkedList mocks */ - MOCK_STATIC_METHOD_1(, void, DList_InitializeListHead, PDLIST_ENTRY, listHead) - BASEIMPLEMENTATION::DList_InitializeListHead(listHead); - MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_1(, int, DList_IsListEmpty, PDLIST_ENTRY, listHead) - int result2 = BASEIMPLEMENTATION::DList_IsListEmpty(listHead); - MOCK_METHOD_END(int, result2) - - MOCK_STATIC_METHOD_2(, void, DList_InsertTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry) - BASEIMPLEMENTATION::DList_InsertTailList(listHead, listEntry); - MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_2(, void, DList_InsertHeadList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry) - BASEIMPLEMENTATION::DList_InsertHeadList(listHead, listEntry); - MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_2(, void, DList_AppendTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, ListToAppend) - BASEIMPLEMENTATION::DList_AppendTailList(listHead, ListToAppend); - MOCK_VOID_METHOD_END() - - MOCK_STATIC_METHOD_1(, int, DList_RemoveEntryList, PDLIST_ENTRY, listEntry) - int result2 = BASEIMPLEMENTATION::DList_RemoveEntryList(listEntry); - MOCK_METHOD_END(int, result2) - - MOCK_STATIC_METHOD_1(, PDLIST_ENTRY, DList_RemoveHeadList, PDLIST_ENTRY, listHead) - PDLIST_ENTRY entry = BASEIMPLEMENTATION::DList_RemoveHeadList(listHead); - MOCK_METHOD_END(PDLIST_ENTRY, entry) - - MOCK_STATIC_METHOD_1(, time_t, get_time, time_t*, t) - MOCK_METHOD_END(time_t, 0); - - MOCK_STATIC_METHOD_4(, STRING_HANDLE, SASToken_Create, STRING_HANDLE, key, STRING_HANDLE, scope, STRING_HANDLE, keyName, size_t, expiry) - STRING_HANDLE tokenResult = BASEIMPLEMENTATION::STRING_new(); - MOCK_METHOD_END(STRING_HANDLE, tokenResult); -}; - -DECLARE_GLOBAL_MOCK_METHOD_0(CMQTTAPIMocks, , LOCK_HANDLE, Lock_Init); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , LOCK_RESULT, Lock, LOCK_HANDLE, handle); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , LOCK_RESULT, Unlock, LOCK_HANDLE, handle); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , LOCK_RESULT, Lock_Deinit, LOCK_HANDLE, handle); - -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , void*, gballoc_malloc, size_t, size); -DECLARE_GLOBAL_MOCK_METHOD_2(CMQTTAPIMocks, , void*, gballoc_realloc, void*, ptr, size_t, size); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , void, gballoc_free, void*, ptr); - -DECLARE_GLOBAL_MOCK_METHOD_0(CMQTTAPIMocks, , STRING_HANDLE, STRING_new); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , STRING_HANDLE, STRING_clone, STRING_HANDLE, handle); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , STRING_HANDLE, STRING_construct, const char*, s); - -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , void, STRING_delete, STRING_HANDLE, s); -DECLARE_GLOBAL_MOCK_METHOD_2(CMQTTAPIMocks, , int, STRING_concat, STRING_HANDLE, s1, const char*, s2); -DECLARE_GLOBAL_MOCK_METHOD_2(CMQTTAPIMocks, , int, STRING_concat_with_STRING, STRING_HANDLE, s1, STRING_HANDLE, s2); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , int, STRING_empty, STRING_HANDLE, s1); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , const char*, STRING_c_str, STRING_HANDLE, s); - -DECLARE_GLOBAL_MOCK_METHOD_5(CMQTTAPIMocks, , int, MQTTClient_setCallbacks,MQTTClient, handle, void*, context, MQTTClient_connectionLost* ,cl, MQTTClient_messageArrived*, ma, MQTTClient_deliveryComplete*, dc); -DECLARE_GLOBAL_MOCK_METHOD_5(CMQTTAPIMocks, , int, MQTTClient_create, MQTTClient*, handle, const char*, serverURI, const char*, clientId, int, persistence_type, void*, persistence_context); -DECLARE_GLOBAL_MOCK_METHOD_2(CMQTTAPIMocks, , int, MQTTClient_connect, MQTTClient, handle, MQTTClient_connectOptions*, options); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , void, MQTTClient_free, void*, ptr); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , void, MQTTClient_destroy, MQTTClient*, handle); -DECLARE_GLOBAL_MOCK_METHOD_2(CMQTTAPIMocks, , int, MQTTClient_disconnect, MQTTClient, handle, int, timeout); -DECLARE_GLOBAL_MOCK_METHOD_3(CMQTTAPIMocks, , int, MQTTClient_subscribe, MQTTClient, handle, const char*, topic, int, qos); -DECLARE_GLOBAL_MOCK_METHOD_2(CMQTTAPIMocks, , int, MQTTClient_unsubscribe, MQTTClient, handle, const char*, topic); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, ,void, MQTTClient_freeMessage,MQTTClient_message**, msg); -DECLARE_GLOBAL_MOCK_METHOD_4(CMQTTAPIMocks, , int, MQTTClient_publishMessage, MQTTClient, handle, const char*, topicName, MQTTClient_message*, msg, MQTTClient_deliveryToken*, dt); - -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , void, DList_InitializeListHead, PDLIST_ENTRY, listHead); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , int, DList_IsListEmpty, PDLIST_ENTRY, listHead); -DECLARE_GLOBAL_MOCK_METHOD_2(CMQTTAPIMocks, , void, DList_InsertTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry); -DECLARE_GLOBAL_MOCK_METHOD_2(CMQTTAPIMocks, , void, DList_InsertHeadList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, listEntry); -DECLARE_GLOBAL_MOCK_METHOD_2(CMQTTAPIMocks, , void, DList_AppendTailList, PDLIST_ENTRY, listHead, PDLIST_ENTRY, ListToAppend); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , int, DList_RemoveEntryList, PDLIST_ENTRY, listEntry); -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , PDLIST_ENTRY, DList_RemoveHeadList, PDLIST_ENTRY, listHead); - -DECLARE_GLOBAL_MOCK_METHOD_1(CMQTTAPIMocks, , time_t, get_time, time_t*, t) -DECLARE_GLOBAL_MOCK_METHOD_4(CMQTTAPIMocks, , STRING_HANDLE, SASToken_Create, STRING_HANDLE, key, STRING_HANDLE, scope, STRING_HANDLE, keyName, size_t, expiry) - -static MICROMOCK_MUTEX_HANDLE g_testByTest; -static MICROMOCK_GLOBAL_SEMAPHORE_HANDLE g_dllByDll; - - -BEGIN_TEST_SUITE(mqttapi_paho_unittests) - -TEST_SUITE_INITIALIZE(TestClassInitialize) -{ - INITIALIZE_MEMORY_DEBUG(g_dllByDll); - g_testByTest = MicroMockCreateMutex(); - ASSERT_IS_NOT_NULL(g_testByTest); -} - -TEST_SUITE_CLEANUP(TestClassCleanup) -{ - MicroMockDestroyMutex(g_testByTest); - DEINITIALIZE_MEMORY_DEBUG(g_dllByDll); -} - -TEST_FUNCTION_INITIALIZE(TestMethodInitialize) -{ - if (!MicroMockAcquireMutex(g_testByTest)) - { - ASSERT_FAIL("our mutex is ABANDONED. Failure in test framework"); - } - - currentmalloc_call = 0; - whenShallmalloc_fail = 0; - - currentrealloc_call = 0; - whenShallrealloc_fail = 0; - - currentSTRING_new_call = 0; - whenShallSTRING_new_fail = 0; - - currentSTRING_clone_call = 0; - whenShallSTRING_clone_fail = 0; - - currentSTRING_construct_call = 0; - whenShallSTRING_construct_fail = 0; - - currentSTRING_concat_call = 0; - whenShallSTRING_concat_fail = 0; - - currentSTRING_empty_call = 0; - whenShallSTRING_empty_fail = 0; - - currentSTRING_concat_with_STRING_call = 0; - whenShallSTRING_concat_with_STRING_fail = 0; - -} - -TEST_FUNCTION_CLEANUP(TestMethodCleanup) -{ - if (!MicroMockReleaseMutex(g_testByTest)) - { - ASSERT_FAIL("failure in test framework at ReleaseMutex"); - } -} - -/* Tests_SRS_MQTTAPI_04_011: [If any member of the parameter options is NULL or empty then MQTTAPI_Create shall return NULL.] */ -TEST_FUNCTION(MQTTAPI_Create_with_NULL_options_fails) -{ - /// arrange - CMQTTAPIMocks mocks; - - /// act - auto result = MQTTAPI_Create(NULL); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - -} - -/* Tests_SRS_MQTTAPI_04_011: [If any member of the parameter options is NULL or empty then MQTTAPI_Create shall return NULL.] */ -TEST_FUNCTION(MQTTAPI_Create_with_NULL_deviceId_fails) -{ - /// arrange - CMQTTAPIMocks mocks; - - const MQTTAPI_ConnectOptions TEST_CONFIG_MQTTAPIconnectionOptions_NULL_DEVICEID = - { - NULL,/*const char* deviceId; */ - TEST_DEVICE_KEY,/*const char* deviceKey; */ - TEST_IOTHUB_NAME,/*const char* serverURI; */ - }; - - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions_NULL_DEVICEID); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - -} - -/* Tests_SRS_MQTTAPI_04_011: [If any member of the parameter options is NULL or empty then MQTTAPI_Create shall return NULL.] */ -TEST_FUNCTION(MQTTAPI_Create_with_Empty_deviceId_fails) -{ - /// arrange - CMQTTAPIMocks mocks; - - const MQTTAPI_ConnectOptions TEST_CONFIG_MQTTAPIconnectionOptions_EMPTY_DEVICEID = - { - "",/*const char* deviceId; */ - TEST_DEVICE_KEY,/*const char* deviceKey; */ - TEST_IOTHUB_NAME,/*const char* serverURI; */ - }; - - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions_EMPTY_DEVICEID); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - -} - -/* Tests_SRS_MQTTAPI_04_011: [If any member of the parameter options is NULL or empty then MQTTAPI_Create shall return NULL.] */ -TEST_FUNCTION(MQTTAPI_Create_with_NULL_deviceKey_fails) -{ - /// arrange - CMQTTAPIMocks mocks; - - const MQTTAPI_ConnectOptions TEST_CONFIG_MQTTAPIconnectionOptions_NULL_DEVICEKEY = - { - TEST_DEVICE_ID,/*const char* deviceId; */ - NULL,/*const char* deviceKey; */ - TEST_IOTHUB_NAME,/*const char* serverURI; */ - }; - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions_NULL_DEVICEKEY); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - -} - -/* Tests_SRS_MQTTAPI_04_011: [If any member of the parameter options is NULL or empty then MQTTAPI_Create shall return NULL.] */ -TEST_FUNCTION(MQTTAPI_Create_with_EMPTY_deviceKey_fails) -{ - /// arrange - CMQTTAPIMocks mocks; - - const MQTTAPI_ConnectOptions TEST_CONFIG_MQTTAPIconnectionOptions_EMPTY_DEVICEKEY = - { - TEST_DEVICE_ID,/*const char* deviceId; */ - NULL,/*const char* deviceKey; */ - TEST_IOTHUB_NAME,/*const char* serverURI; */ - }; - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions_EMPTY_DEVICEKEY); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - -} - -/* Tests_SRS_MQTTAPI_04_011: [If any member of the parameter options is NULL or empty then MQTTAPI_Create shall return NULL.] */ -TEST_FUNCTION(MQTTAPI_Create_with_NULL_serverURI_fails) -{ - /// arrange - CMQTTAPIMocks mocks; - - const MQTTAPI_ConnectOptions TEST_CONFIG_MQTTAPIconnectionOptions_NULL_SERVERURI = - { - TEST_DEVICE_ID,/*const char* deviceId; */ - TEST_DEVICE_KEY,/*const char* deviceKey; */ - NULL,/*const char* serverURI; */ - }; - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions_NULL_SERVERURI); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - -} - -/* Tests_SRS_MQTTAPI_04_011: [If any member of the parameter options is NULL or empty then MQTTAPI_Create shall return NULL.] */ -TEST_FUNCTION(MQTTAPI_Create_with_EMPTY_serverURI_fails) -{ - /// arrange - CMQTTAPIMocks mocks; - - const MQTTAPI_ConnectOptions TEST_CONFIG_MQTTAPIconnectionOptions_EMPTY_SERVERURI = - { - TEST_DEVICE_ID,/*const char* deviceId; */ - TEST_DEVICE_KEY,/*const char* deviceKey; */ - "",/*const char* serverURI; */ - }; - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions_EMPTY_SERVERURI); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - -} - -/* Tests_SRS_MQTTAPI_04_012: [Parameters deviceId, deviceKey and sasTokenSr shall be saved.] */ -/* Tests_SRS_MQTTAPI_04_014: [Otherwise, MQTTAPI_Create shall return a MQTTAPI_HANDLE suitable for further calls to the module.] */ -/* Tests_SRS_MQTTAPI_04_024: [MQTTAPI_Create shall call underlying library connection functions to establish connection with the server.] */ -/* Tests_SRS_MQTTAPI_04_047: [Otherwise MQTTAPI_Create shall return a non-NULL MQTTAPI_HANDLE] */ -TEST_FUNCTION(MQTTAPI_Create_with_valid_connectionOptions_succeed) -{ - /// arrange - CMQTTAPIMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_CONFIG_MQTTAPIconnectionOptions.deviceId)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_CONFIG_MQTTAPIconnectionOptions.deviceKey)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_CONFIG_MQTTAPIconnectionOptions.sasTokenSr)); - - STRICT_EXPECTED_CALL(mocks, get_time(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, STRING_new()); - - STRICT_EXPECTED_CALL(mocks, SASToken_Create(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, MQTTClient_create(IGNORED_PTR_ARG, TEST_CONFIG_MQTTAPIconnectionOptions.serverURI, TEST_CONFIG_MQTTAPIconnectionOptions.deviceId, MQTTCLIENT_PERSISTENCE_NONE, NULL)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, MQTTClient_setCallbacks(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); //UserName for connect. - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); //Password for connect. - - STRICT_EXPECTED_CALL(mocks, MQTTClient_connect(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, Lock_Init()); - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions); - - /// assert - ASSERT_IS_NOT_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - MQTTAPI_Destroy(result); -} - -/* Tests_SRS_MQTTAPI_04_025: [If connection fails MQTTAPI_Create shall return NULL. */ -TEST_FUNCTION(MQTTAPI_Create_MQTTClient_connect_fail_fails) -{ - /// arrange - CMQTTAPIMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_CONFIG_MQTTAPIconnectionOptions.deviceId)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_CONFIG_MQTTAPIconnectionOptions.deviceKey)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_CONFIG_MQTTAPIconnectionOptions.sasTokenSr)); - - STRICT_EXPECTED_CALL(mocks, MQTTClient_create(IGNORED_PTR_ARG, TEST_CONFIG_MQTTAPIconnectionOptions.serverURI, TEST_CONFIG_MQTTAPIconnectionOptions.deviceId, MQTTCLIENT_PERSISTENCE_NONE, NULL)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, MQTTClient_setCallbacks(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, STRING_new()); - - STRICT_EXPECTED_CALL(mocks, get_time(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, SASToken_Create(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); //UserName for connect. - - STRICT_EXPECTED_CALL(mocks, STRING_c_str(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); //Password for connect. - - STRICT_EXPECTED_CALL(mocks, MQTTClient_connect(IGNORED_PTR_ARG, IGNORED_PTR_ARG)) - .IgnoreAllArguments() - .SetReturn(__LINE__); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, MQTTClient_destroy(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, gballoc_free(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, Lock_Init()); - STRICT_EXPECTED_CALL(mocks, Lock_Deinit(TEST_LOCK_HANDLE)); - - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - MQTTAPI_Destroy(result); -} - -/* Tests_SRS_MQTTAPI_04_015: [If creating instance fails for any reason, then MQTTAPI_Create shall return NULL.] */ -TEST_FUNCTION(MQTTAPI_Create_allocation_of_handledata_fails_fail) -{ - /// arrange - CMQTTAPIMocks mocks; - - whenShallmalloc_fail = 1; - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - MQTTAPI_Destroy(result); -} -/* Tests_SRS_MQTTAPI_04_013: [If saving these parameters fail for any reason MQTTAPI_Create shall return NULL.] */ -TEST_FUNCTION(MQTTAPI_Create_construct_deviceId_fail_fail) -{ - /// arrange - CMQTTAPIMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, Lock_Init()); - STRICT_EXPECTED_CALL(mocks, Lock_Deinit(TEST_LOCK_HANDLE)); - - whenShallSTRING_construct_fail = 1; - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_CONFIG_MQTTAPIconnectionOptions.deviceId)); - - STRICT_EXPECTED_CALL(mocks, gballoc_free(IGNORED_PTR_ARG)) - .IgnoreArgument(1);; - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - MQTTAPI_Destroy(result); -} - -/* Tests_SRS_MQTTAPI_04_013: [If saving these parameters fail for any reason MQTTAPI_Create shall return NULL.] */ -TEST_FUNCTION(MQTTAPI_Create_construct_deviceKey_fail_fail) -{ - /// arrange - CMQTTAPIMocks mocks; - - STRICT_EXPECTED_CALL(mocks, gballoc_malloc(IGNORED_NUM_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, DList_InitializeListHead(IGNORED_PTR_ARG)).IgnoreArgument(1); - - whenShallSTRING_construct_fail = 2; - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_CONFIG_MQTTAPIconnectionOptions.deviceId)); - STRICT_EXPECTED_CALL(mocks, STRING_construct(TEST_CONFIG_MQTTAPIconnectionOptions.deviceKey)); - - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, gballoc_free(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, Lock_Init()); - STRICT_EXPECTED_CALL(mocks, Lock_Deinit(TEST_LOCK_HANDLE)); - - /// act - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions); - - /// assert - ASSERT_IS_NULL(result); - mocks.AssertActualAndExpectedCalls(); - - ///clenup - MQTTAPI_Destroy(result); -} - -/* Tests_SRS_MQTTAPI_04_021: [If parameter instance is NULL then MQTTAPI_Destroy shall take no action.] */ -TEST_FUNCTION(MQTTAPI_Destroy_with_NULL_instance_shall_do_nothing) -{ - /// arrange - CMQTTAPIMocks mocks; - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions); - mocks.ResetAllCalls(); - - /// act - - MQTTAPI_Destroy(NULL); - - /// assert - mocks.AssertActualAndExpectedCalls(); - - ///clenup - MQTTAPI_Destroy(result); -} - -/* Tests_SRS_MQTTAPI_04_022: [MQTTAPI_Destroy shall free all resources used by MQTTAPI_HANDLE.] */ -/* Tests_SRS_MQTTAPI_04_049: [If the instance is connected, MQTTAPI_Destroy shall disconnect the instance] */ -TEST_FUNCTION(MQTTAPI_Destroy_shall_release_all_mqttapihandle_resources) -{ - /// arrange - CMQTTAPIMocks mocks; - auto result = MQTTAPI_Create(&TEST_CONFIG_MQTTAPIconnectionOptions); - mocks.ResetAllCalls(); - - /// act - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - STRICT_EXPECTED_CALL(mocks, STRING_delete(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, MQTTClient_disconnect(IGNORED_PTR_ARG, 0)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, MQTTClient_destroy(IGNORED_PTR_ARG)) - .IgnoreAllArguments(); - - STRICT_EXPECTED_CALL(mocks, gballoc_free(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - STRICT_EXPECTED_CALL(mocks, Lock_Deinit(TEST_LOCK_HANDLE)); - - STRICT_EXPECTED_CALL(mocks, DList_RemoveHeadList(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, DList_RemoveHeadList(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - STRICT_EXPECTED_CALL(mocks, DList_RemoveHeadList(IGNORED_PTR_ARG)) - .IgnoreArgument(1); - - MQTTAPI_Destroy(result); - - /// assert - mocks.AssertActualAndExpectedCalls(); - - ///clenup -} - -END_TEST_SUITE(mqttapi_paho_unittests) diff --git a/c/serializer/samples/simplesample_mqtt/CMakeLists.txt b/c/serializer/samples/simplesample_mqtt/CMakeLists.txt index cc4df68e..bfcf3915 100644 --- a/c/serializer/samples/simplesample_mqtt/CMakeLists.txt +++ b/c/serializer/samples/simplesample_mqtt/CMakeLists.txt @@ -29,15 +29,12 @@ IF(WIN32) ENDIF(WIN32) include_directories(. ${SHARED_UTIL_INC_FOLDER} ${IOTHUB_CLIENT_INC_FOLDER}) -link_directories(${whatIsBuilding}_dll ${SHARED_UTIL_LIB_DIR}) +#link_directories(${whatIsBuilding}_dll ${SHARED_UTIL_LIB_DIR}) add_executable(simplesample_mqtt ${simplesample_mqtt_c_files} ${simplesample_mqtt_h_files}) target_link_libraries(simplesample_mqtt + iothub_client_mqtt_transport serializer iothub_client - iothub_client_mqtt_transport ) - -linkSharedUtil(simplesample_mqtt) -linkPaho(simplesample_mqtt) diff --git a/c/serializer/samples/simplesample_mqtt/windows/simplesample_mqtt.vcxproj b/c/serializer/samples/simplesample_mqtt/windows/simplesample_mqtt.vcxproj index 44c8672a..5140ca81 100644 --- a/c/serializer/samples/simplesample_mqtt/windows/simplesample_mqtt.vcxproj +++ b/c/serializer/samples/simplesample_mqtt/windows/simplesample_mqtt.vcxproj @@ -113,7 +113,7 @@ Console true - $(PAHO_PATH)\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\$(Configuration)\paho-mqtt3cs.lib;%(AdditionalDependencies) + %(AdditionalDependencies) @@ -133,7 +133,7 @@ Console true - $(PAHO_PATH)\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\$(Platform)\$(Configuration)\paho-mqtt3cs.lib;%(AdditionalDependencies) + %(AdditionalDependencies) @@ -153,7 +153,7 @@ true true true - $(PAHO_PATH)\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\$(Configuration)\paho-mqtt3cs.lib;%(AdditionalDependencies) + %(AdditionalDependencies) @@ -177,7 +177,7 @@ true true true - $(PAHO_PATH)\org.eclipse.paho.mqtt.c\Windows Build\paho-mqtt3cs\$(Platform)\$(Configuration)\paho-mqtt3cs.lib;%(AdditionalDependencies) + %(AdditionalDependencies)