Topic template extension maintenance (#2022)

* Topic templates: Ensure parameter values are checked for wildcard

* Topic templates: Complement extension methods

- add template.BuildMessage()
- add subscribeOptionsBuilder.WithTopicTemplate()

* Topic templates: switch some samples to use a topic template

The changes should be self-explanatory and are
intended to provide more examples.

* Topic templates: add README
This commit is contained in:
simonthum
2024-06-22 14:54:11 +02:00
committed by GitHub
parent 8650002523
commit c5f4cf1f9b
10 changed files with 264 additions and 54 deletions
@@ -45,6 +45,29 @@ namespace MQTTnet.Tests.Extensions
var template = new MqttTopicTemplate("A/B/{foo}/D");
template.WithParameter("foo", "a#");
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void RejectsReservedChars2()
{
var template = new MqttTopicTemplate("A/B/{foo}/D");
template.WithParameter("foo", "a+b");
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void RejectsReservedChars3()
{
var template = new MqttTopicTemplate("A/B/{foo}/D");
template.WithParameter("foo", "a/b");
}
[TestMethod]
public void AcceptsEmptyValue()
{
var template = new MqttTopicTemplate("A/B/{foo}/D");
template.WithParameter("foo", "");
}
[TestMethod]
[ExpectedException(typeof(MqttProtocolViolationException))]
@@ -60,13 +83,6 @@ namespace MQTTnet.Tests.Extensions
var _ = new MqttTopicTemplate(null);
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void RejectsReservedChars2()
{
var template = new MqttTopicTemplate("A/B/{foo}/D");
template.WithParameter("foo", "e/f");
}
[TestMethod]
public void IgnoresEmptyParameters()
@@ -114,6 +130,50 @@ namespace MQTTnet.Tests.Extensions
Assert.AreEqual("A/v1/+/F", filter.Topic);
}
[TestMethod]
public void SubscriptionSupport2()
{
var template = new MqttTopicTemplate("A/v1/{param}/F");
var subscribeOptions = new MqttFactory().CreateSubscribeOptionsBuilder()
.WithTopicTemplate(template)
.WithSubscriptionIdentifier(5)
.Build();
Assert.AreEqual("A/v1/+/F", subscribeOptions.TopicFilters[0].Topic);
}
[TestMethod]
public void SendAndSubscribeSupport()
{
var template = new MqttTopicTemplate("App/v1/{sender}/message");
var filter = new MqttTopicFilterBuilder()
.WithTopicTemplate(template)
.WithAtLeastOnceQoS()
.WithNoLocal()
.Build();
Assert.AreEqual("App/v1/+/message", filter.Topic);
var myTopic = template.WithParameter("sender", "me, myself & i");
var message = new MqttApplicationMessageBuilder()
.WithTopicTemplate(
myTopic)
.WithPayload("Hello!")
.Build();
Assert.IsTrue(message.MatchesTopicTemplate(template));
}
[TestMethod]
public void SendAndSubscribeSupport2()
{
var template = new MqttTopicTemplate("App/v1/{sender}/message");
Assert.ThrowsException<ArgumentException>(() =>
template.BuildMessage());
}
[TestMethod]
public void CanonicalPrefixFilter()
{
+17 -4
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using MQTTnet.Extensions.TopicTemplate;
namespace MQTTnet.Tests
{
@@ -31,31 +32,43 @@ namespace MQTTnet.Tests
{
maxNumLevel3Topics = 1;
}
MqttTopicTemplate baseTemplate = new MqttTopicTemplate("{publisher}/{building}/{level}/{sensor}");
for (var p = 0; p < numPublishers; ++p)
{
int publisherTopicCount = 0;
var publisherName = "pub" + p;
var publisherTemplate = baseTemplate
.WithParameter("publisher", publisherName);
for (var l1 = 0; l1 < numLevel1Topics; ++l1)
{
var l1Template = publisherTemplate.WithParameter("building", "building" + (l1 + 1));
for (var l2 = 0; l2 < numLevel2Topics; ++l2)
{
var l2Template = l1Template.WithParameter("level", "level" + (l2 + 1));
for (var l3 = 0; l3 < maxNumLevel3Topics; ++l3)
{
if (publisherTopicCount >= numTopicsPerPublisher)
break;
var topic = string.Format("{0}/building{1}/level{2}/sensor{3}", publisherName, l1 + 1, l2 + 1, l3 + 1);
AddPublisherTopic(publisherName, topic, topicsByPublisher);
var l3Template = l2Template
.WithParameter("sensor", "sensor" + (l3 + 1));
AddPublisherTopic(publisherName, l3Template.TopicFilter, topicsByPublisher);
if (l2 == 0)
{
var singleWildcardTopic = string.Format("{0}/building{1}/+/sensor{2}", publisherName, l1 + 1, l3 + 1);
var singleWildcardTopic = l1Template
.WithParameter("sensor", "sensor" + (l3 + 1))
.TopicFilter;
AddPublisherTopic(publisherName, singleWildcardTopic, singleWildcardTopicsByPublisher);
}
if ((l1 == 0) && (l3 == 0))
{
var multiWildcardTopic = string.Format("{0}/+/level{1}/+", publisherName, l2 + 1);
var multiWildcardTopic = publisherTemplate
.WithParameter("level", "level" + (l2 + 1))
.TopicFilter;
AddPublisherTopic(publisherName, multiWildcardTopic, multiWildcardTopicsByPublisher);
}