diff options
author | Maurice Kalinowski <maurice.kalinowski@qt.io> | 2023-11-26 10:49:04 +0100 |
---|---|---|
committer | Maurice Kalinowski <maurice.kalinowski@qt.io> | 2023-11-30 09:57:18 +0100 |
commit | 95b38eafb514832a951a5c67f3a2af9ff8fb83de (patch) | |
tree | 63bd10eab85ff49f57e3a2591832f76e1f014880 | |
parent | 648a2da86537776b075e9e9062de5ae2deb1429d (diff) |
Fix handling of multiple wildcards
The matching check for topic filters did not take into account that a
mixture of wildcards is valid. While # is only allowed a single time,
using + is valid in multiple occasions and can also me mixed with other
wildcards.
Fixes: QTBUG-104478
Pick-to: 6.6 6.5 6.2
Change-Id: I04129d5fbbb21c95115a15d74c6787804a8d0b10
Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
-rw-r--r-- | src/mqtt/qmqtttopicfilter.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qmqttsubscription/tst_qmqttsubscription.cpp | 32 | ||||
-rw-r--r-- | tests/auto/qmqtttopicfilter/tst_qmqtttopicfilter.cpp | 6 |
3 files changed, 39 insertions, 1 deletions
diff --git a/src/mqtt/qmqtttopicfilter.cpp b/src/mqtt/qmqtttopicfilter.cpp index d6796f9..6c96ff8 100644 --- a/src/mqtt/qmqtttopicfilter.cpp +++ b/src/mqtt/qmqtttopicfilter.cpp @@ -223,7 +223,7 @@ bool QMqttTopicFilter::match(const QMqttTopicName &name, MatchOptions matchOptio return false; for (int i = 0; i < filterLevels.size(); ++i) { - if (filterLevels.at(i) != topicLevels.at(i)) + if (filterLevels.at(i) != topicLevels.at(i) && filterLevels.at(i) != QLatin1Char('+')) return false; } return true; diff --git a/tests/auto/qmqttsubscription/tst_qmqttsubscription.cpp b/tests/auto/qmqttsubscription/tst_qmqttsubscription.cpp index bdb3e7d..b32dec3 100644 --- a/tests/auto/qmqttsubscription/tst_qmqttsubscription.cpp +++ b/tests/auto/qmqttsubscription/tst_qmqttsubscription.cpp @@ -30,6 +30,7 @@ private Q_SLOTS: void noLocal_data(); void noLocal(); void qtbug_106203(); + void qtbug_104478(); private: void createAndSubscribe(QMqttClient *c, QMqttSubscription **sub, const QString &topic); QProcess m_brokerProcess; @@ -450,6 +451,37 @@ void Tst_QMqttSubscription::qtbug_106203() QTRY_VERIFY2(client.state() == QMqttClient::Disconnected, "Could not disconnect from broker."); } +void Tst_QMqttSubscription::qtbug_104478() +{ + QMqttClient client; + client.setHostname(m_testBroker); + client.setPort(m_port); + + client.connectToHost(); + QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker."); + + auto singleWildcardSub = client.subscribe(QLatin1String("test/+/+/test2")); + QTRY_VERIFY2(singleWildcardSub->state() == QMqttSubscription::Subscribed, "Could not subscribe to topic."); + QSignalSpy singleSpy(singleWildcardSub, SIGNAL(messageReceived(QMqttMessage))); + + auto mixedWildcardSub = client.subscribe(QLatin1String("test/+/#")); + QTRY_VERIFY2(mixedWildcardSub->state() == QMqttSubscription::Subscribed, "Could not subscribe to topic."); + QSignalSpy mixedSpy(mixedWildcardSub, SIGNAL(messageReceived(QMqttMessage))); + + + const QString topic(QLatin1String("test/foo/bar/test2")); + + QSignalSpy pubSpy(&client, SIGNAL(messageSent(qint32))); + client.publish(topic, "Wildcard checks", 1); + QTRY_VERIFY2(pubSpy.size() == 1, "Could not publish message."); + + QTRY_VERIFY2(singleSpy.count() == 1, "Did not receive message"); + QTRY_VERIFY2(mixedSpy.count() == 1, "Did not receive message"); + + client.disconnectFromHost(); + QTRY_VERIFY2(client.state() == QMqttClient::Disconnected, "Could not disconnect from broker."); +} + QTEST_MAIN(Tst_QMqttSubscription) #include "tst_qmqttsubscription.moc" diff --git a/tests/auto/qmqtttopicfilter/tst_qmqtttopicfilter.cpp b/tests/auto/qmqtttopicfilter/tst_qmqtttopicfilter.cpp index 925fb5c..dcd1c2f 100644 --- a/tests/auto/qmqtttopicfilter/tst_qmqtttopicfilter.cpp +++ b/tests/auto/qmqtttopicfilter/tst_qmqtttopicfilter.cpp @@ -83,6 +83,12 @@ void Tst_QMqttTopicFilter::matches() QVERIFY(QMqttTopicFilter("/+").match(QMqttTopicName("/finance"))); QVERIFY(!QMqttTopicFilter("+").match(QMqttTopicName("/finance"))); + // QTBUG-104478 + filter = QMqttTopicFilter("sport/+/player1/#"); + QVERIFY(filter.match(QMqttTopicName("sport/tennis/player1/ranking"))); + filter = QMqttTopicFilter("sport/+/+"); + QVERIFY(filter.match(QMqttTopicName("sport/tennis/player2"))); + // Non normative comment's examples [4.7.2] QVERIFY(QMqttTopicFilter("#").match(QMqttTopicName("$SYS/foo"))); QVERIFY(!QMqttTopicFilter("#").match(QMqttTopicName("$SYS/foo"), QMqttTopicFilter::WildcardsDontMatchDollarTopicMatchOption)); |