diff --git a/MQTTSNGateway/src/MQTTSNGWClient.cpp b/MQTTSNGateway/src/MQTTSNGWClient.cpp index 31d65ce..f9da50e 100644 --- a/MQTTSNGateway/src/MQTTSNGWClient.cpp +++ b/MQTTSNGateway/src/MQTTSNGWClient.cpp @@ -736,11 +736,6 @@ bool Topic::isMatch(string* topicName) { string::size_type tlen = _topicName->size(); - if (topicName->size() < tlen - 2) - { - return false; - } - string::size_type tpos = 0; string::size_type tloc = 0; string::size_type pos = 0; @@ -809,17 +804,22 @@ bool Topic::isMatch(string* topicName) return false; } } - else if ( loc != string::npos && tloc == string::npos ) + else if ( loc == string::npos && tloc != string::npos ) { - tloc = _topicName->find('#', --tpos); - if ( tloc == string::npos ) + string subtopic = topicName->substr(pos); + string subtopict = _topicName->substr(tpos, tloc - tpos); + if ( subtopic != subtopict) { return false; } - else - { - return true; - } + + tpos = tloc + 1; + + return _topicName->substr(tpos) == wildcard; + } + else if ( loc != string::npos && tloc == string::npos ) + { + return _topicName->substr(tpos) == wildcard; } } } @@ -854,7 +854,8 @@ uint16_t Topics::getTopicId(const MQTTSN_topicid* topicid) Topic* p = _first; while (p) { - if (strncmp(p->_topicName->c_str(), topicid->data.long_.name, topicid->data.long_.len) == 0) + if ( (int)strlen(p->_topicName->c_str()) == topicid->data.long_.len && + strncmp(p->_topicName->c_str(), topicid->data.long_.name, topicid->data.long_.len) == 0) { return p->_topicId; } @@ -882,7 +883,8 @@ Topic* Topics::getTopic(const MQTTSN_topicid* topicid) Topic* p = _first; while (p) { - if (strncmp(p->_topicName->c_str(), topicid->data.long_.name, topicid->data.long_.len) == 0 ) + if ( (int)strlen(p->_topicName->c_str()) == topicid->data.long_.len && + strncmp(p->_topicName->c_str(), topicid->data.long_.name, topicid->data.long_.len) == 0 ) { return p; } diff --git a/MQTTSNGateway/src/tests/TestTopics.cpp b/MQTTSNGateway/src/tests/TestTopics.cpp index 3c48bd6..12f228f 100644 --- a/MQTTSNGateway/src/tests/TestTopics.cpp +++ b/MQTTSNGateway/src/tests/TestTopics.cpp @@ -12,6 +12,7 @@ * * Contributors: * Tomoaki Yamaguchi - initial API and implementation + * Tieto Poland Sp. z o.o. - Topic test improvements **************************************************************************************/ #include @@ -32,12 +33,55 @@ TestTopics::~TestTopics() delete _topics; } +bool testIsMatch(const char* topicFilter, const char* topicName) +{ + string* filter = new string(topicFilter); + string* name = new string(topicName); + + Topic topic(filter); + bool isMatch = topic.isMatch(name); + + delete name; + + return isMatch; +} + +bool testGetTopic(const char* topicName, const char* searchedTopicName) +{ + Topics topics; + string name(topicName); + MQTTSN_topicid topicid; + topicid.type = MQTTSN_TOPIC_TYPE_NORMAL; + topicid.data.long_.len = strlen(searchedTopicName); + topicid.data.long_.name = const_cast(searchedTopicName); + + topics.add(&name); + + return topics.getTopic(&topicid) != 0; +} + +bool testGetTopicId(const char* topicName, const char* searchedTopicName) +{ + Topics topics; + string name(topicName); + MQTTSN_topicid topicid; + topicid.type = MQTTSN_TOPIC_TYPE_NORMAL; + topicid.data.long_.len = strlen(searchedTopicName); + topicid.data.long_.name = const_cast(searchedTopicName); + + topics.add(&name); + + return topics.getTopicId(&topicid) != 0; +} + void TestTopics::test(void) { printf("Test Topics "); - MQTTSN_topicid topic[12]; - char tp[12][10]; + const int TOPIC_COUNT = 13; + + MQTTSN_topicid topic[TOPIC_COUNT]; + char tp[TOPIC_COUNT][10]; /* create Topic */ strcpy(tp[0], "Topic/+"); @@ -48,13 +92,12 @@ void TestTopics::test(void) for ( int i = 1; i < 10 ; i++ ) { - strcpy(tp[i], "Topic/+/"); - tp[i][8] = 0x30 + i; - tp[i][9] = 0; + sprintf(tp[i], "Topic/+/%d", i); topic[i].type = MQTTSN_TOPIC_TYPE_NORMAL; topic[i].data.long_.len = strlen(tp[i]); topic[i].data.long_.name = tp[i]; } + strcpy(tp[10], "TOPIC/#"); tp[10][7] = 0; topic[10].type = MQTTSN_TOPIC_TYPE_NORMAL; @@ -67,8 +110,14 @@ void TestTopics::test(void) topic[11].data.long_.len = strlen(tp[11]); topic[11].data.long_.name = tp[11]; + tp[12][0] = '#'; + tp[12][1] = 0; + topic[12].type = MQTTSN_TOPIC_TYPE_NORMAL; + topic[12].data.long_.len = strlen(tp[12]); + topic[12].data.long_.name = tp[12]; + /* Add Topic to Topics */ - for ( int i = 0; i < 12; i++ ) + for ( int i = 0; i < TOPIC_COUNT; i++ ) { MQTTSN_topicid pos = topic[i]; Topic* t = _topics->add(&pos); @@ -86,7 +135,7 @@ void TestTopics::test(void) } /* Get Topic by MQTTSN_topicid */ - for ( int i = 0; i < 12; i++ ) + for ( int i = 0; i < TOPIC_COUNT; i++ ) { Topic* t = _topics->getTopic(&topic[i]); //printf("Topic=%s ID=%d ID=%d\n", t->getTopicName()->c_str(), t->getTopicId(),_topics->getTopicId(&topic[i])); @@ -94,23 +143,19 @@ void TestTopics::test(void) } /* Get TopicId by MQTTSN_topicid */ - for ( int i = 0; i < 12; i++ ) + for ( int i = 0; i < TOPIC_COUNT; i++ ) { uint16_t id = _topics->getTopicId(&topic[i]); //printf("ID=%d \n", id); assert(id == i + 1); } - /* Test Wilecard */ + /* Test Wildcard */ for ( int i = 0; i < 10 ; i++ ) { MQTTSN_topicid tp1; char tp0[10]; - strcpy(tp0, "Topic/"); - tp0[6] = 0x30 + i; - tp0[7] = '/'; - tp0[8] = 0x30 + i; - tp0[9] = 0; + sprintf(tp0, "Topic/%d/%d", i, i); tp1.type = MQTTSN_TOPIC_TYPE_NORMAL; tp1.data.long_.len = strlen(tp0); tp1.data.long_.name = tp0; @@ -128,13 +173,12 @@ void TestTopics::test(void) */ assert(t != 0); } + for ( int i = 0; i < 10 ; i++ ) { MQTTSN_topicid tp1; char tp0[10]; - strcpy(tp0, "Topic/"); - tp0[6] = 0x30 + i; - tp0[7] = 0; + sprintf(tp0, "Topic/%d", i); tp1.type = MQTTSN_TOPIC_TYPE_NORMAL; tp1.data.long_.len = strlen(tp0); tp1.data.long_.name = tp0; @@ -151,17 +195,14 @@ void TestTopics::test(void) } */ assert(t != 0); + assert(t->getTopicName()->compare(tp[0]) == 0); } for ( int i = 0; i < 10 ; i++ ) { MQTTSN_topicid tpid1; char tp0[10]; - strcpy(tp0, "TOPIC/"); - tp0[6] = 0x30 + i; - tp0[7] = '/'; - tp0[8] = 0x30 + i; - tp0[9] = 0; + sprintf(tp0, "TOPIC/%d/%d", i, i); tpid1.type = MQTTSN_TOPIC_TYPE_NORMAL; tpid1.data.long_.len = strlen(tp0); tpid1.data.long_.name = tp0; @@ -178,6 +219,80 @@ void TestTopics::test(void) } */ assert( t != 0); + assert(t->getTopicName()->compare(tp[10]) == 0); } + + { + MQTTSN_topicid tp1; + char tp0[10]; + strcpy(tp0, "Topic"); + tp1.type = MQTTSN_TOPIC_TYPE_NORMAL; + tp1.data.long_.len = strlen(tp0); + tp1.data.long_.name = tp0; + + Topic* t = _topics->match(&tp1); + + assert(t != 0); + assert(t->getTopicName()->compare(tp[12]) == 0); + } + + { + MQTTSN_topicid tp1; + char tp0[20]; + strcpy(tp0, "Topic/multi/level"); + tp1.type = MQTTSN_TOPIC_TYPE_NORMAL; + tp1.data.long_.len = strlen(tp0); + tp1.data.long_.name = tp0; + + Topic* t = _topics->match(&tp1); + + assert(t != 0); + assert(t->getTopicName()->compare(tp[12]) == 0); + } + + + assert(testIsMatch("#", "one")); + assert(testIsMatch("#", "one/")); + assert(testIsMatch("#", "one/two")); + assert(testIsMatch("#", "one/two/")); + assert(testIsMatch("#", "one/two/three")); + assert(testIsMatch("#", "one/two/three/")); + + assert(!testIsMatch("one/+", "one")); + assert(testIsMatch("one/+", "one/")); + assert(testIsMatch("one/+", "one/two")); + assert(!testIsMatch("one/+", "one/two/")); + assert(!testIsMatch("one/+", "one/two/three")); + + assert(!testIsMatch("one/+/three/+", "one/two/three")); + assert(testIsMatch("one/+/three/+", "one/two/three/")); + assert(testIsMatch("one/+/three/+", "one/two/three/four")); + assert(!testIsMatch("one/+/three/+", "one/two/three/four/")); + + assert(testIsMatch("one/+/three/#", "one/two/three")); + assert(testIsMatch("one/+/three/#", "one/two/three/")); + assert(testIsMatch("one/+/three/#", "one/two/three/four")); + assert(testIsMatch("one/+/three/#", "one/two/three/four/")); + assert(testIsMatch("one/+/three/#", "one/two/three/four/five")); + + // examples from MQTT specification + assert(testIsMatch("sport/tennis/player1/#", "sport/tennis/player1")); + assert(testIsMatch("sport/tennis/player1/#", "sport/tennis/player1/ranking")); + assert(testIsMatch("sport/tennis/player1/#", "sport/tennis/player1/score/wimbledon")); + assert(testIsMatch("sport/tennis/+", "sport/tennis/player1")); + assert(testIsMatch("sport/tennis/+", "sport/tennis/player2")); + assert(!testIsMatch("sport/tennis/+", "sport/tennis/player1/ranking")); + assert(testIsMatch("+/+", "/finance")); + assert(testIsMatch("/+", "/finance")); + assert(!testIsMatch("+", "/finance")); + + assert(testGetTopicId("mytopic", "mytopic")); + assert(!testGetTopicId("mytopic", "mytop")); + assert(!testGetTopicId("mytopic", "mytopiclong")); + + assert(testGetTopic("mytopic", "mytopic")); + assert(!testGetTopic("mytopic", "mytop")); + assert(!testGetTopic("mytopic", "mytopiclong")); + printf("[ OK ]\n"); }