mirror of
https://github.com/eclipse-paho/paho.mqtt.cpp.git
synced 2025-09-15 12:58:39 +08:00
TopicMatcher matching to parent when using '#' wildcard.
This commit is contained in:
parent
55f7fecdda
commit
670b38df37
@ -312,12 +312,21 @@ public:
|
||||
auto snode = std::move(nodes_.back());
|
||||
nodes_.pop_back();
|
||||
|
||||
const auto map_end = snode.node_->children.end();
|
||||
typename node_map::iterator child;
|
||||
|
||||
// If we're at the end of the topic fields, we either have a value,
|
||||
// or need to move on to the next node to search.
|
||||
if (snode.fields_.empty()) {
|
||||
pval_ = snode.node_->content.get();
|
||||
if (!pval_)
|
||||
if (!pval_) {
|
||||
// ...but a '#' matches the parent topic
|
||||
if ((child = snode.node_->children.find("#")) != map_end) {
|
||||
pval_ = child->second->content.get();
|
||||
return;
|
||||
}
|
||||
this->next();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -325,9 +334,6 @@ public:
|
||||
auto field = std::move(snode.fields_.front());
|
||||
snode.fields_.pop_front();
|
||||
|
||||
typename node_map::iterator child;
|
||||
const auto map_end = snode.node_->children.end();
|
||||
|
||||
// Look for an exact match
|
||||
if ((child = snode.node_->children.find(field)) != map_end) {
|
||||
nodes_.push_back({child->second.get(), snode.fields_});
|
||||
|
||||
@ -109,7 +109,10 @@ bool topic_filter::matches(const string& topic) const
|
||||
{
|
||||
auto n = fields_.size();
|
||||
|
||||
// Edge case of topic_filter("")
|
||||
// Spec: All Topic Names and Topic Filters MUST be at least one
|
||||
// character long [MQTT-4.7.3-1]
|
||||
// So, an empty filter can't match anything, and is technically an
|
||||
// error.
|
||||
if (n == 0) {
|
||||
return false;
|
||||
}
|
||||
@ -118,7 +121,7 @@ bool topic_filter::matches(const string& topic) const
|
||||
auto nt = topic_fields.size();
|
||||
|
||||
// Filter can't match a topic that is shorter
|
||||
if (n > nt) {
|
||||
if (n > nt && !(n == nt + 1 && fields_[n - 1] == "#")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -140,6 +143,9 @@ bool topic_filter::matches(const string& topic) const
|
||||
if (fields_[i] == "#") {
|
||||
break;
|
||||
}
|
||||
if (i == nt && i < n - 1) {
|
||||
return fields_[i + 1] == "#";
|
||||
}
|
||||
if (fields_[i] != "+" && fields_[i] != topic_fields[i]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -578,8 +578,7 @@ TEST_CASE("async_client publish 5 args", "[client]")
|
||||
|
||||
const void* payload{PAYLOAD.data()};
|
||||
const size_t payload_size{PAYLOAD.size()};
|
||||
delivery_token_ptr token_pub{
|
||||
cli.publish(TOPIC, payload, payload_size, GOOD_QOS, RETAINED)
|
||||
delivery_token_ptr token_pub{cli.publish(TOPIC, payload, payload_size, GOOD_QOS, RETAINED)
|
||||
};
|
||||
REQUIRE(token_pub);
|
||||
token_pub->wait_for(TIMEOUT);
|
||||
@ -738,8 +737,8 @@ TEST_CASE("async_client subscribe many topics 2 args_single", "[client]")
|
||||
cli.connect()->wait();
|
||||
REQUIRE(cli.is_connected());
|
||||
|
||||
mqtt::const_string_collection_ptr TOPIC_1_COLL{mqtt::string_collection::create({"TOPIC0"}
|
||||
)};
|
||||
mqtt::const_string_collection_ptr TOPIC_1_COLL{mqtt::string_collection::create({"TOPIC0"})
|
||||
};
|
||||
iasync_client::qos_collection GOOD_QOS_1_COLL{0};
|
||||
try {
|
||||
cli.subscribe(TOPIC_1_COLL, GOOD_QOS_1_COLL)->wait_for(TIMEOUT);
|
||||
|
||||
@ -534,8 +534,8 @@ public:
|
||||
|
||||
// NOTE: Only tokens for messages with QOS=1 and QOS=2 are kept. That's
|
||||
// why the vector's size does not account for QOS=0 message tokens
|
||||
std::vector<mqtt::delivery_token_ptr> tokens_pending{cli.get_pending_delivery_tokens(
|
||||
)};
|
||||
std::vector<mqtt::delivery_token_ptr> tokens_pending{cli.get_pending_delivery_tokens()
|
||||
};
|
||||
CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(tokens_pending.size()));
|
||||
|
||||
mqtt::token_ptr token_disconn{cli.disconnect()};
|
||||
@ -831,8 +831,7 @@ public:
|
||||
CPPUNIT_ASSERT(cli.is_connected());
|
||||
|
||||
mqtt::test::dummy_action_listener listener;
|
||||
mqtt::token_ptr token_sub{
|
||||
cli.subscribe(TOPIC_COLL, GOOD_QOS_COLL, &CONTEXT, listener)
|
||||
mqtt::token_ptr token_sub{cli.subscribe(TOPIC_COLL, GOOD_QOS_COLL, &CONTEXT, listener)
|
||||
};
|
||||
CPPUNIT_ASSERT(token_sub);
|
||||
token_sub->wait_for(TIMEOUT);
|
||||
|
||||
@ -232,6 +232,7 @@ TEST_CASE("topic matches", "[topic_filter]")
|
||||
REQUIRE(filt.matches("my/topic/name"));
|
||||
REQUIRE(filt.matches("my/topic/id"));
|
||||
REQUIRE(filt.matches("my/topic/name/and/id"));
|
||||
REQUIRE(filt.matches("my/topic"));
|
||||
|
||||
REQUIRE(!filt.matches("my/other/name"));
|
||||
REQUIRE(!filt.matches("my/other/id"));
|
||||
@ -244,14 +245,14 @@ TEST_CASE("topic matches", "[topic_filter]")
|
||||
SECTION("should_match")
|
||||
{
|
||||
REQUIRE(topic_filter{"foo/bar"}.matches("foo/bar"));
|
||||
REQUIRE(
|
||||
topic_filter{
|
||||
REQUIRE(topic_filter{
|
||||
"foo/+",
|
||||
}
|
||||
.matches("foo/bar")
|
||||
);
|
||||
.matches("foo/bar"));
|
||||
REQUIRE(topic_filter{"foo/+/baz"}.matches("foo/bar/baz"));
|
||||
REQUIRE(topic_filter{"foo/+/#"}.matches("foo/bar/baz"));
|
||||
REQUIRE(topic_filter("foo/bar/#").matches("foo/bar/baz"));
|
||||
REQUIRE(topic_filter("foo/bar/#").matches("foo/bar"));
|
||||
REQUIRE(topic_filter{"A/B/+/#"}.matches("A/B/B/C"));
|
||||
REQUIRE(topic_filter{"#"}.matches("foo/bar/baz"));
|
||||
REQUIRE(topic_filter{"#"}.matches("/foo/bar"));
|
||||
|
||||
@ -69,6 +69,8 @@ TEST_CASE("matcher matches", "[topic_matcher]")
|
||||
REQUIRE((topic_matcher<int>{{"foo/+", 42}}.has_match("foo/bar")));
|
||||
REQUIRE((topic_matcher<int>{{"foo/+/baz", 42}}.has_match("foo/bar/baz")));
|
||||
REQUIRE((topic_matcher<int>{{"foo/+/#", 42}}.has_match("foo/bar/baz")));
|
||||
REQUIRE((topic_matcher<int>{{"foo/bar/#", 42}}.has_match("foo/bar/baz")));
|
||||
REQUIRE((topic_matcher<int>{{"foo/bar/#", 42}}.has_match("foo/bar")));
|
||||
REQUIRE((topic_matcher<int>{{"A/B/+/#", 42}}.has_match("A/B/B/C")));
|
||||
REQUIRE((topic_matcher<int>{{"#", 42}}.has_match("foo/bar/baz")));
|
||||
REQUIRE((topic_matcher<int>{{"#", 42}}.has_match("/foo/bar")));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user