diff --git a/CMakeLists.txt b/CMakeLists.txt index 34291a3..f0b6f39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,5 +13,7 @@ add_subdirectory(examples/pub) add_subdirectory(examples/sub) add_subdirectory(examples/subunsub) +add_subdirectory(test) + include(packaging) package_component() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8235e56..fb7017e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,8 +13,8 @@ include_directories( ) set(SRC_LIST - ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/threadcontext.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/threadcontext.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mqttpublisherbase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mqttsubscriberbase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/clientpaho.cpp diff --git a/src/mqttclient.cpp b/src/mqttclient.cpp index a4d2564..42eafb8 100644 --- a/src/mqttclient.cpp +++ b/src/mqttclient.cpp @@ -215,9 +215,17 @@ void MqttClient::disconnect() Token MqttClient::publish(const MqttMessage& message, int qos) { - if (hasWildcard(message.topic()) || !isValidTopic(message.topic())) { + if (hasWildcard(message.topic())) + { + LogDebug("[MqttClient::publish]","Topic has wildcard : " + message.topic()); return Token(m_clientId, -1); } + else if(!isValidTopic(message.topic())) + { + LogDebug("[MqttClient::publish]","Topic is invalid : " + message.topic()); + return Token(m_clientId, -1); + } + OSDEV_COMPONENTS_LOCKGUARD(m_interfaceMutex); IMqttClientImpl* client(nullptr); { @@ -239,6 +247,13 @@ Token MqttClient::publish(const MqttMessage& message, int qos) } client = m_principalClient.get(); } + + if(!client) + { + LogDebug("[MqttClient::publish]", "Invalid pointer to IMqttClient retrieved."); + return Token(m_clientId, -1); + } + return Token(client->clientId(), client->publish(message, qos)); } diff --git a/src/mqttutil.cpp b/src/mqttutil.cpp index 4f22c15..a7b3376 100644 --- a/src/mqttutil.cpp +++ b/src/mqttutil.cpp @@ -55,7 +55,12 @@ bool isValidTopic( const std::string &topic ) bool hasWildcard( const std::string &topic ) { - return ( topic.size() > 0 && (topic.find( '+' ) != std::string::npos || topic.size() - 1 == '#' ) ); + return ( topic.size() > 0 && + ( + topic.find( '+' ) != std::string::npos || + topic.back() == '#' + ) + ); } bool testForOverlap( const std::string &existingTopic, const std::string &newTopic ) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..1471cf8 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,30 @@ +#**************************************************************************** +#* Copyright (c) 2023 Open Systems Development B.V. +#***************************************************************************** +# +# Don't call this file directly from cmake. +# This file is included from the upper directory. +# +# Build rules for the MQTT Library + +add_executable(topictest + TopicLengthTest.cpp +) + +target_include_directories(topictest PRIVATE + ${CMAKE_CIRRENT_SOURECE_DIR} + ../include +) + +target_link_libraries(topictest PRIVATE + gmock_main + gmock + gtest + mqtt-cpp +) + +add_test(NAME topictest COMMAND topictest) + +set_tests_properties(topictest PROPERTIES + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +) diff --git a/test/TopicLengthTest.cpp b/test/TopicLengthTest.cpp new file mode 100644 index 0000000..b36bc78 --- /dev/null +++ b/test/TopicLengthTest.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** + * COpyright (c) 2023 Open Systems Development B.V. + ****************************************************************************/ + +#include +#include +#include +#include + +#include "mqttclient.h" + +using namespace osdev::components::mqtt; +using namespace osdev::components::log; + +static const std::string main_topic = "test/"; + +/**************************************************************************** + * H E L P E R C L A S S E S + ****************************************************************************/ +class Publisher +{ +public: + Publisher() : m_mqtt_client("TopicTester"){} + 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, + osdev::components::mqtt::Credentials(username, password), + osdev::components::mqtt::mqtt_LWT(lwt_topic, lwt_message), + true, + osdev::components::log::LogSettings + { + osdev::components::log::LogLevel::Debug, + osdev::components::log::LogMask::None + }); + } + + void publish(const std::string &message_topic, const std::string &message_payload) + { + osdev::components::mqtt::MqttMessage message(message_topic, true, false, message_payload); + osdev::components::mqtt::Token t_result = m_mqtt_client.publish(message, 0); + } + +private: + osdev::components::mqtt::MqttClient m_mqtt_client; +}; + +/// @brief class to generate a cumulative topic.. +class TopicTester +{ + public: + TopicTester(std::shared_ptr publisher) : m_publisher(publisher){} + virtual ~TopicTester(){} + + void RunTopicTester(int max_number_of_chars) + { + for(int nCount = 1; nCount < max_number_of_chars; nCount++) + { + std::string subtopic(nCount, 'a'); + std::string topic = std::string(main_topic + subtopic); + std::string message(std::to_string(topic.size()) + " (" + std::to_string(subtopic.size()) + ")"); + + m_publisher->publish(topic, message); + } + } + + private: + std::shared_ptr m_publisher; +}; + +/***************************************************************************** + * T H E A C T U A L T E S T S + *****************************************************************************/ +/// TopicTester +TEST(topictest, TopicLengthTest) +{ + std::shared_ptr pPublisher = std::make_shared(); + pPublisher->connect("127.0.0.1", 1883); + + TopicTester oTester(pPublisher); + + oTester.RunTopicTester(101); +}