diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9f91f79..835cfc3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,25 +7,26 @@ # # Build rules for the MQTT Library -add_executable(topictest +add_executable(mqtt_test + helperclasses/PublisherClass.h TopicLengthTest.cpp SledgeHammerTest.cpp ) -target_include_directories(topictest PRIVATE +target_include_directories(mqtt_test PRIVATE ${CMAKE_CIRRENT_SOURECE_DIR} ../include ) -target_link_libraries(topictest PRIVATE +target_link_libraries(mqtt_test PRIVATE gmock_main gmock gtest mqtt-cpp ) -add_test(NAME topictest COMMAND topictest) +add_test(NAME mqtt_test COMMAND mqtt_test) -set_tests_properties(topictest PROPERTIES +set_tests_properties(mqtt_test PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" ) diff --git a/test/SledgeHammerTest.cpp b/test/SledgeHammerTest.cpp index 66f51ff..6ad4194 100644 --- a/test/SledgeHammerTest.cpp +++ b/test/SledgeHammerTest.cpp @@ -6,9 +6,179 @@ #include #include #include +#include +#include -#include "mqttclient.h" +#include -using namespace osdev::components::mqtt; -using namespace osdev::components::log; +#include "helperclasses/PublisherClass.h" +/// Every test does basically the same. +/// 1. Create a Publisher object +/// 2. Connect to the MQTT broker +/// 3. Publish 10 message(s) +/// 4. Disconnect from the MQTT broker +/// 5. Destroy the Publisher object +/// 6. Repeat 10 times. + +const std::string sledge_maintopic = "SledgeHammerTest/"; + +enum TIME_RES +{ + T_MICRO, + T_MILLI, + T_SECONDS +}; + +std::uint64_t getEpochUSecs() +{ + auto tsUSec =std::chrono::time_point_cast(std::chrono::system_clock::now()); + return static_cast(tsUSec.time_since_epoch().count()); +} + + +void sleepcp( int number, TIME_RES resolution = T_MILLI ) // Cross-platform sleep function +{ + int factor = 0; // Should not happen.. + + switch( resolution ) + { + case T_MICRO: + factor = 1; + break; + + case T_MILLI: + factor = 1000; + break; + + case T_SECONDS: + factor = 1000000; + break; + } + + usleep( number * factor ); +} + +/// Test a single connection, 1 time +TEST(SledgeHammerTest, SingleConnectionCleanExit) +{ + Publisher *publisher = nullptr; + for (int test_counter = 0; test_counter < 10; test_counter++) + { + publisher = new Publisher(std::to_string(getEpochUSecs())); + if(publisher) + { + publisher->connect("localhost"); + publisher->publish(sledge_maintopic + "Single Connection Clean Exit Test/" + std::to_string(test_counter), "Hello World. I'm alive.."); + publisher->disconnect(); + delete publisher; + publisher = nullptr; + } + } +} + +TEST(SledgeHammerTest, SingleConnectionForcedExit) +{ + Publisher *publisher = nullptr; + for (int test_counter = 0; test_counter < 10; test_counter++) + { + publisher = new Publisher(std::to_string(getEpochUSecs())); + if(publisher) + { + publisher->connect("localhost"); + publisher->publish(sledge_maintopic + "Single Connection Forced Exit/Test/" + std::to_string(test_counter), "Hello World. I'm alive.."); + delete publisher; + publisher = nullptr; + } + } +} + +TEST(SledgeHammerTest, MultipleConnections_10_CleanExit) +{ + std::unordered_map publishers; + + for (int test_counter = 0; test_counter < 10; test_counter++) + { + publishers["Publisher" + std::to_string(test_counter)] = new Publisher(std::to_string(getEpochUSecs())); + if(publishers["Publisher" + std::to_string(test_counter)]) + { + publishers["Publisher" + std::to_string(test_counter)]->connect("localhost"); + } + } + + for (int test_counter = 0; test_counter < 10; test_counter++) + { + for (int nCount = 0; nCount < 10; nCount++) + { + publishers["Publisher" + std::to_string(test_counter)]->publish(sledge_maintopic + "Multiple Connections [10]/Clean Exit/Test " + std::to_string(test_counter), "Hello World. I'm alive.."); + } + publishers["Publisher" + std::to_string(test_counter)]->disconnect(); + delete publishers["Publisher" + std::to_string(test_counter)]; + publishers.erase("Publisher" + std::to_string(test_counter)); + } +} + +TEST(SledgeHammerTest, MultipleConnections_BurnTest) +{ + std::unordered_map publishers; + + const int max_run = 100; + const int max_connections = 10; + const int max_messages = 10; + + for (int test_run = 0; test_run < max_run; test_run++) + { + std::cout << "Creating " << max_connections << " connections for test run " << test_run << " " << std::endl; + for (int test_counter = 0; test_counter < max_connections; test_counter++) + { + publishers["Publisher" + std::to_string(test_counter)] = new Publisher(std::to_string(getEpochUSecs())); + if(publishers["Publisher" + std::to_string(test_counter)]) + { + publishers["Publisher" + std::to_string(test_counter)]->connect("localhost"); + std::cout << "."; + } + } + std::cout << std::endl; + + // Wait a second for the connections to be established. + sleepcp(1, T_SECONDS); + + std::cout << "Publishing " << max_messages << " messages for test run " << test_run << std::endl; + for (int test_counter = 0; test_counter < max_connections; test_counter++) + { + std::cout << "\tConnection : " << test_counter << " "; + for (int nCount = 0; nCount < max_messages; nCount++) + { + if(publishers["Publisher" + std::to_string(test_counter)]) + { + std::cout << "."; + publishers["Publisher" + std::to_string(test_counter)]->publish(sledge_maintopic + + "Multiple Connections [" + std::to_string(max_connections) + "]/Multi Messages [" + std::to_string(max_messages) + "]/Test Run " + + std::to_string(test_run) + "/" + "[" + std::to_string(test_counter) + "]" + + "[" + std::to_string(nCount) + "]", "Hello World. I'm alive.."); + } + } + std::cout << std::endl; + } + + // Wait another second to update the broker. + sleepcp(1, T_SECONDS); + + std::cout << "Disconnecting " << max_connections << " connections for test run " << test_run << " "; + for (int test_counter = 0; test_counter < max_connections; test_counter++) + { + if(publishers["Publisher" + std::to_string(test_counter)]) + { + std::cout << "."; + publishers["Publisher" + std::to_string(test_counter)]->disconnect(); + delete publishers["Publisher" + std::to_string(test_counter)]; + } + } + std::cout << std::endl; + publishers.clear(); + std::cout << std::string(200,'=') << std::endl; + + // Wait for another second before re-running another 100 times. + sleepcp(1, T_SECONDS); + } +} \ No newline at end of file diff --git a/test/TopicLengthTest.cpp b/test/TopicLengthTest.cpp index b36bc78..3a9f817 100644 --- a/test/TopicLengthTest.cpp +++ b/test/TopicLengthTest.cpp @@ -12,7 +12,7 @@ using namespace osdev::components::mqtt; using namespace osdev::components::log; -static const std::string main_topic = "test/"; +static const std::string main_topic = "Topic Length Test/"; /**************************************************************************** * H E L P E R C L A S S E S diff --git a/test/helperclasses/PublisherClass.h b/test/helperclasses/PublisherClass.h index f550474..8d12cb7 100644 --- a/test/helperclasses/PublisherClass.h +++ b/test/helperclasses/PublisherClass.h @@ -5,17 +5,46 @@ #include "mqttclient.h" #include -#include using namespace osdev::components::mqtt; using namespace osdev::components::log; -static const std::string main_topic = "test/"; - class Publisher { public: - Publisher() : m_mqtt_client("TopicTester"){} + Publisher(const std::string &unique_id) : m_mqtt_client("SledgeHammerTest" + unique_id){} virtual ~Publisher() {} + void connect( const std::string &hostname, + int portnumber = 1883, + const std::string &username = std::string(), + const std::string &password = std::string(), + const std::string &lwt_topic = std::string(), + const std::string &lwt_message = std::string() + ) + { + m_mqtt_client.connect(hostname, portnumber, + Credentials(username, password), + mqtt_LWT(lwt_topic, lwt_message), + true, + LogSettings + { + LogLevel::Debug, + LogMask::None + }); + } + + void disconnect() + { + m_mqtt_client.disconnect(); + } + + void publish(const std::string &message_topic, const std::string &message_payload) + { + MqttMessage message(message_topic, true, false, message_payload); + Token t_result = m_mqtt_client.publish(message, 0); + } + +private: + osdev::components::mqtt::MqttClient m_mqtt_client; }; \ No newline at end of file