mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-21 04:03:05 +08:00
Improve topic comparer.
This commit is contained in:
@@ -37,13 +37,13 @@ namespace MQTTnet.Benchmarks
|
||||
{
|
||||
for (var i = 0; i < 10000; i++)
|
||||
{
|
||||
MqttTopicFilterComparer.IsMatch("sport/tennis/player1", "sport/#");
|
||||
MqttTopicFilterComparer.IsMatch("sport/tennis/player1/ranking", "sport/#/ranking");
|
||||
MqttTopicFilterComparer.IsMatch("sport/tennis/player1/score/wimbledon", "sport/+/player1/#");
|
||||
MqttTopicFilterComparer.IsMatch("sport/tennis/player1", "sport/tennis/+");
|
||||
MqttTopicFilterComparer.IsMatch("/finance", "+/+");
|
||||
MqttTopicFilterComparer.IsMatch("/finance", "/+");
|
||||
MqttTopicFilterComparer.IsMatch("/finance", "+");
|
||||
MqttTopicFilterComparer.Compare("sport/tennis/player1", "sport/#");
|
||||
MqttTopicFilterComparer.Compare("sport/tennis/player1/ranking", "sport/#/ranking");
|
||||
MqttTopicFilterComparer.Compare("sport/tennis/player1/score/wimbledon", "sport/+/player1/#");
|
||||
MqttTopicFilterComparer.Compare("sport/tennis/player1", "sport/tennis/+");
|
||||
MqttTopicFilterComparer.Compare("/finance", "+/+");
|
||||
MqttTopicFilterComparer.Compare("/finance", "/+");
|
||||
MqttTopicFilterComparer.Compare("/finance", "+");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -202,248 +202,7 @@ namespace MQTTnet.Tests.Server
|
||||
Assert.AreEqual(1, receivedMessagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Intercept_Subscription()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithSubscriptionInterceptor(
|
||||
c =>
|
||||
{
|
||||
// Set the topic to "a" regards what the client wants to subscribe.
|
||||
c.TopicFilter.Topic = "a";
|
||||
}));
|
||||
|
||||
var topicAReceived = false;
|
||||
var topicBReceived = false;
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
client.UseApplicationMessageReceivedHandler(c =>
|
||||
{
|
||||
if (c.ApplicationMessage.Topic == "a")
|
||||
{
|
||||
topicAReceived = true;
|
||||
}
|
||||
else if (c.ApplicationMessage.Topic == "b")
|
||||
{
|
||||
topicBReceived = true;
|
||||
}
|
||||
});
|
||||
|
||||
await client.SubscribeAsync("b");
|
||||
|
||||
await client.PublishAsync("a");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.IsTrue(topicAReceived);
|
||||
Assert.IsFalse(topicBReceived);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_Unsubscribe()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var receivedMessagesCount = 0;
|
||||
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("c1"));
|
||||
c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("c2"));
|
||||
|
||||
var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
|
||||
await c2.PublishAsync(message);
|
||||
|
||||
await Task.Delay(500);
|
||||
Assert.AreEqual(0, receivedMessagesCount);
|
||||
|
||||
var subscribeEventCalled = false;
|
||||
server.ClientSubscribedTopicHandler = new MqttServerClientSubscribedTopicHandlerDelegate(e =>
|
||||
{
|
||||
subscribeEventCalled = e.TopicFilter.Topic == "a" && e.ClientId == c1.Options.ClientId;
|
||||
});
|
||||
|
||||
await c1.SubscribeAsync(new MqttTopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
|
||||
await Task.Delay(250);
|
||||
Assert.IsTrue(subscribeEventCalled, "Subscribe event not called.");
|
||||
|
||||
await c2.PublishAsync(message);
|
||||
await Task.Delay(250);
|
||||
Assert.AreEqual(1, receivedMessagesCount);
|
||||
|
||||
var unsubscribeEventCalled = false;
|
||||
server.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(e =>
|
||||
{
|
||||
unsubscribeEventCalled = e.TopicFilter == "a" && e.ClientId == c1.Options.ClientId;
|
||||
});
|
||||
|
||||
await c1.UnsubscribeAsync("a");
|
||||
await Task.Delay(250);
|
||||
Assert.IsTrue(unsubscribeEventCalled, "Unsubscribe event not called.");
|
||||
|
||||
await c2.PublishAsync(message);
|
||||
await Task.Delay(500);
|
||||
Assert.AreEqual(1, receivedMessagesCount);
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.AreEqual(1, receivedMessagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_Multiple_In_Single_Request()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var receivedMessagesCount = 0;
|
||||
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter("a")
|
||||
.WithTopicFilter("b")
|
||||
.WithTopicFilter("c")
|
||||
.Build());
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
|
||||
await c2.PublishAsync("a");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 1);
|
||||
|
||||
await c2.PublishAsync("b");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 2);
|
||||
|
||||
await c2.PublishAsync("c");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 3);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_Lots_In_Single_Request()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var receivedMessagesCount = 0;
|
||||
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
|
||||
var optionsBuilder = new MqttClientSubscribeOptionsBuilder();
|
||||
for (var i = 0; i < 500; i++)
|
||||
{
|
||||
optionsBuilder.WithTopicFilter(i.ToString(), MqttQualityOfServiceLevel.AtMostOnce);
|
||||
}
|
||||
|
||||
await c1.SubscribeAsync(optionsBuilder.Build()).ConfigureAwait(false);
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
|
||||
var messageBuilder = new MqttApplicationMessageBuilder();
|
||||
for (var i = 0; i < 500; i++)
|
||||
{
|
||||
messageBuilder.WithTopic(i.ToString());
|
||||
|
||||
await c2.PublishAsync(messageBuilder.Build()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
SpinWait.SpinUntil(() => receivedMessagesCount == 500, TimeSpan.FromSeconds(20));
|
||||
|
||||
Assert.AreEqual(500, receivedMessagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_Lots_In_Multiple_Requests()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var receivedMessagesCount = 0;
|
||||
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
|
||||
for (var i = 0; i < 500; i++)
|
||||
{
|
||||
var so = new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter(i.ToString()).Build();
|
||||
|
||||
await c1.SubscribeAsync(so).ConfigureAwait(false);
|
||||
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
|
||||
var messageBuilder = new MqttApplicationMessageBuilder();
|
||||
for (var i = 0; i < 500; i++)
|
||||
{
|
||||
messageBuilder.WithTopic(i.ToString());
|
||||
|
||||
await c2.PublishAsync(messageBuilder.Build()).ConfigureAwait(false);
|
||||
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
SpinWait.SpinUntil(() => receivedMessagesCount == 500, 5000);
|
||||
|
||||
Assert.AreEqual(500, receivedMessagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_Multiple_In_Multiple_Request()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var receivedMessagesCount = 0;
|
||||
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter("a")
|
||||
.Build());
|
||||
|
||||
await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter("b")
|
||||
.Build());
|
||||
|
||||
await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter("c")
|
||||
.Build());
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
|
||||
await c2.PublishAsync("a");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 1);
|
||||
|
||||
await c2.PublishAsync("b");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 2);
|
||||
|
||||
await c2.PublishAsync("c");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public async Task Publish_From_Server()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Subscribing;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
@@ -23,5 +24,23 @@ namespace MQTTnet.Tests.Server
|
||||
Assert.IsFalse(connectResult.SharedSubscriptionAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscription_Of_Shared_Subscription_Is_Denied()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client = testEnvironment.CreateClient();
|
||||
await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
|
||||
.WithProtocolVersion(MqttProtocolVersion.V500)
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
|
||||
|
||||
var subscribeResult = await client.SubscribeAsync("$share/A");
|
||||
|
||||
Assert.AreEqual(MqttClientSubscribeResultCode.SharedSubscriptionsNotSupported, subscribeResult.Items[0].ResultCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Client.Subscribing;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Subscribe_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Intercept_Subscription()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithSubscriptionInterceptor(
|
||||
c =>
|
||||
{
|
||||
// Set the topic to "a" regards what the client wants to subscribe.
|
||||
c.TopicFilter.Topic = "a";
|
||||
}));
|
||||
|
||||
var topicAReceived = false;
|
||||
var topicBReceived = false;
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
client.UseApplicationMessageReceivedHandler(c =>
|
||||
{
|
||||
if (c.ApplicationMessage.Topic == "a")
|
||||
{
|
||||
topicAReceived = true;
|
||||
}
|
||||
else if (c.ApplicationMessage.Topic == "b")
|
||||
{
|
||||
topicBReceived = true;
|
||||
}
|
||||
});
|
||||
|
||||
await client.SubscribeAsync("b");
|
||||
|
||||
await client.PublishAsync("a");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.IsTrue(topicAReceived);
|
||||
Assert.IsFalse(topicBReceived);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_Unsubscribe()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var receivedMessagesCount = 0;
|
||||
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("c1"));
|
||||
c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("c2"));
|
||||
|
||||
var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
|
||||
await c2.PublishAsync(message);
|
||||
|
||||
await Task.Delay(500);
|
||||
Assert.AreEqual(0, receivedMessagesCount);
|
||||
|
||||
var subscribeEventCalled = false;
|
||||
server.ClientSubscribedTopicHandler = new MqttServerClientSubscribedTopicHandlerDelegate(e =>
|
||||
{
|
||||
subscribeEventCalled = e.TopicFilter.Topic == "a" && e.ClientId == c1.Options.ClientId;
|
||||
});
|
||||
|
||||
await c1.SubscribeAsync(new MqttTopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
|
||||
await Task.Delay(250);
|
||||
Assert.IsTrue(subscribeEventCalled, "Subscribe event not called.");
|
||||
|
||||
await c2.PublishAsync(message);
|
||||
await Task.Delay(250);
|
||||
Assert.AreEqual(1, receivedMessagesCount);
|
||||
|
||||
var unsubscribeEventCalled = false;
|
||||
server.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(e =>
|
||||
{
|
||||
unsubscribeEventCalled = e.TopicFilter == "a" && e.ClientId == c1.Options.ClientId;
|
||||
});
|
||||
|
||||
await c1.UnsubscribeAsync("a");
|
||||
await Task.Delay(250);
|
||||
Assert.IsTrue(unsubscribeEventCalled, "Unsubscribe event not called.");
|
||||
|
||||
await c2.PublishAsync(message);
|
||||
await Task.Delay(500);
|
||||
Assert.AreEqual(1, receivedMessagesCount);
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.AreEqual(1, receivedMessagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_Multiple_In_Single_Request()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var receivedMessagesCount = 0;
|
||||
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter("a")
|
||||
.WithTopicFilter("b")
|
||||
.WithTopicFilter("c")
|
||||
.Build());
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
|
||||
await c2.PublishAsync("a");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 1);
|
||||
|
||||
await c2.PublishAsync("b");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 2);
|
||||
|
||||
await c2.PublishAsync("c");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 3);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_Lots_In_Single_Request()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var receivedMessagesCount = 0;
|
||||
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
|
||||
var optionsBuilder = new MqttClientSubscribeOptionsBuilder();
|
||||
for (var i = 0; i < 500; i++)
|
||||
{
|
||||
optionsBuilder.WithTopicFilter(i.ToString());
|
||||
}
|
||||
|
||||
await c1.SubscribeAsync(optionsBuilder.Build()).ConfigureAwait(false);
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
|
||||
var messageBuilder = new MqttApplicationMessageBuilder();
|
||||
for (var i = 0; i < 500; i++)
|
||||
{
|
||||
messageBuilder.WithTopic(i.ToString());
|
||||
|
||||
await c2.PublishAsync(messageBuilder.Build()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
SpinWait.SpinUntil(() => receivedMessagesCount == 500, TimeSpan.FromSeconds(20));
|
||||
|
||||
Assert.AreEqual(500, receivedMessagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_Lots_In_Multiple_Requests()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var receivedMessagesCount = 0;
|
||||
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
|
||||
for (var i = 0; i < 500; i++)
|
||||
{
|
||||
var so = new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter(i.ToString()).Build();
|
||||
|
||||
await c1.SubscribeAsync(so).ConfigureAwait(false);
|
||||
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
|
||||
var messageBuilder = new MqttApplicationMessageBuilder();
|
||||
for (var i = 0; i < 500; i++)
|
||||
{
|
||||
messageBuilder.WithTopic(i.ToString());
|
||||
|
||||
await c2.PublishAsync(messageBuilder.Build()).ConfigureAwait(false);
|
||||
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
SpinWait.SpinUntil(() => receivedMessagesCount == 500, 5000);
|
||||
|
||||
Assert.AreEqual(500, receivedMessagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_Multiple_In_Multiple_Request()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var receivedMessagesCount = 0;
|
||||
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter("a")
|
||||
.Build());
|
||||
|
||||
await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter("b")
|
||||
.Build());
|
||||
|
||||
await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter("c")
|
||||
.Build());
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
|
||||
await c2.PublishAsync("a");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 1);
|
||||
|
||||
await c2.PublishAsync("b");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 2);
|
||||
|
||||
await c2.PublishAsync("c");
|
||||
await Task.Delay(100);
|
||||
Assert.AreEqual(receivedMessagesCount, 3);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Deny_Invalid_Topic()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithSubscriptionInterceptor(
|
||||
c =>
|
||||
{
|
||||
if (c.TopicFilter.Topic == "not_allowed_topic")
|
||||
{
|
||||
c.ReasonCode = MqttSubscribeReasonCode.TopicFilterInvalid;
|
||||
}
|
||||
}));
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
|
||||
var subscribeResult =await client.SubscribeAsync("allowed_topic");
|
||||
Assert.AreEqual(MqttClientSubscribeResultCode.GrantedQoS0, subscribeResult.Items[0].ResultCode);
|
||||
|
||||
subscribeResult =await client.SubscribeAsync("not_allowed_topic");
|
||||
Assert.AreEqual(MqttClientSubscribeResultCode.TopicFilterInvalid, subscribeResult.Items[0].ResultCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,111 +4,135 @@ using MQTTnet.Server.Internal;
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public class TopicFilterComparer_Tests
|
||||
public sealed class MqttTopicFilterComparer_Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_Plus_Match_With_Separator_Only()
|
||||
public void Plus_Match_With_Separator_Only()
|
||||
{
|
||||
//A Topic Name or Topic Filter consisting only of the ‘/’ character is valid
|
||||
CompareAndAssert("A", "+", true);
|
||||
CompareAndAssert("A", "+", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_Hash_Match_With_Separator_Only()
|
||||
public void Hash_Match_With_Separator_Only()
|
||||
{
|
||||
//A Topic Name or Topic Filter consisting only of the ‘/’ character is valid
|
||||
CompareAndAssert("/", "#", true);
|
||||
CompareAndAssert("/", "#", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_DirectMatch()
|
||||
public void DirectMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C", "A/B/C", true);
|
||||
CompareAndAssert("A/B/C", "A/B/C", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_DirectNoMatch()
|
||||
public void DirectNoMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/X", "A/B/C", false);
|
||||
CompareAndAssert("A/B/X", "A/B/C", MqttTopicFilterCompareResult.NoMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_MiddleOneLevelWildcardMatch()
|
||||
public void MiddleOneLevelWildcardMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C", "A/+/C", true);
|
||||
CompareAndAssert("A/B/C", "A/+/C", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_MiddleOneLevelWildcardNoMatch()
|
||||
public void MiddleOneLevelWildcardNoMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C/D", "A/+/C", false);
|
||||
CompareAndAssert("A/B/C/D", "A/+/C", MqttTopicFilterCompareResult.NoMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_BeginningOneLevelWildcardMatch()
|
||||
public void BeginningOneLevelWildcardMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C", "+/B/C", true);
|
||||
CompareAndAssert("A/B/C", "+/B/C", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_EndOneLevelWildcardMatch()
|
||||
public void EndOneLevelWildcardMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C", "A/B/+", true);
|
||||
CompareAndAssert("A/B/C", "A/B/+", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_EndMultipleLevelsWildcardMatch()
|
||||
public void EndMultipleLevelsWildcardMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C", "A/#", true);
|
||||
CompareAndAssert("A/B/C", "A/#", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_EndMultipleLevelsWildcardNoMatch()
|
||||
public void EndMultipleLevelsWildcardNoMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C/D", "A/C/#", false);
|
||||
CompareAndAssert("A/B/C/D", "A/C/#", MqttTopicFilterCompareResult.NoMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_EndMultipleLevelsWildcardMatchEmptyLevel()
|
||||
public void EndMultipleLevelsWildcardMatchEmptyLevel()
|
||||
{
|
||||
CompareAndAssert("A/", "A/#", true);
|
||||
CompareAndAssert("A/", "A/#", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_AllLevelsWildcardMatch()
|
||||
public void AllLevelsWildcardMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C/D", "#", true);
|
||||
CompareAndAssert("A/B/C/D", "#", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_MultiLevel_Sport()
|
||||
public void MultiLevel_Sport()
|
||||
{
|
||||
// Tests from official MQTT spec (4.7.1.2 Multi-level wildcard)
|
||||
CompareAndAssert("sport/tennis/player1", "sport/tennis/player1/#", true);
|
||||
CompareAndAssert("sport/tennis/player1/ranking", "sport/tennis/player1/#", true);
|
||||
CompareAndAssert("sport/tennis/player1/score/wimbledon", "sport/tennis/player1/#", true);
|
||||
CompareAndAssert("sport/tennis/player1", "sport/tennis/player1/#", MqttTopicFilterCompareResult.IsMatch);
|
||||
CompareAndAssert("sport/tennis/player1/ranking", "sport/tennis/player1/#", MqttTopicFilterCompareResult.IsMatch);
|
||||
CompareAndAssert("sport/tennis/player1/score/wimbledon", "sport/tennis/player1/#", MqttTopicFilterCompareResult.IsMatch);
|
||||
|
||||
CompareAndAssert("sport/tennis/player1", "sport/tennis/+", true);
|
||||
CompareAndAssert("sport/tennis/player2", "sport/tennis/+", true);
|
||||
CompareAndAssert("sport/tennis/player1/ranking", "sport/tennis/+", false);
|
||||
CompareAndAssert("sport/tennis/player1", "sport/tennis/+", MqttTopicFilterCompareResult.IsMatch);
|
||||
CompareAndAssert("sport/tennis/player2", "sport/tennis/+", MqttTopicFilterCompareResult.IsMatch);
|
||||
CompareAndAssert("sport/tennis/player1/ranking", "sport/tennis/+", MqttTopicFilterCompareResult.NoMatch);
|
||||
|
||||
CompareAndAssert("sport", "sport/#", true);
|
||||
CompareAndAssert("sport", "sport/+", false);
|
||||
CompareAndAssert("sport/", "sport/+", true);
|
||||
CompareAndAssert("sport", "sport/#", MqttTopicFilterCompareResult.IsMatch);
|
||||
CompareAndAssert("sport", "sport/+", MqttTopicFilterCompareResult.NoMatch);
|
||||
CompareAndAssert("sport/", "sport/+", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_SingleLevel_Finance()
|
||||
public void SingleLevel_Finance()
|
||||
{
|
||||
// Tests from official MQTT spec (4.7.1.3 Single level wildcard)
|
||||
CompareAndAssert("/finance", "+/+", true);
|
||||
CompareAndAssert("/finance", "/+", true);
|
||||
CompareAndAssert("/finance", "+", false);
|
||||
CompareAndAssert("/finance", "+/+", MqttTopicFilterCompareResult.IsMatch);
|
||||
CompareAndAssert("/finance", "/+", MqttTopicFilterCompareResult.IsMatch);
|
||||
CompareAndAssert("/finance", "+", MqttTopicFilterCompareResult.NoMatch);
|
||||
}
|
||||
|
||||
private static void CompareAndAssert(string topic, string filter, bool expectedResult)
|
||||
|
||||
[TestMethod]
|
||||
public void Reserved_Multi_Level_Wildcard_Only()
|
||||
{
|
||||
Assert.AreEqual(expectedResult, MqttTopicFilterComparer.IsMatch(topic, filter));
|
||||
CompareAndAssert("$SPECIAL/TOPIC", "#", MqttTopicFilterCompareResult.NoMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Reserved_Single_Level_Wildcard_Prefix()
|
||||
{
|
||||
CompareAndAssert("$SYS/monitor/Clients", "+/monitor/Clients", MqttTopicFilterCompareResult.NoMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Reserved_Single_Level_Wildcard_Suffix()
|
||||
{
|
||||
CompareAndAssert("$SYS/monitor/Clients", "$SYS/monitor/+", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Reserved_Single_Level_Wildcard()
|
||||
{
|
||||
CompareAndAssert("$SYS/monitor/Clients", "$SYS/#", MqttTopicFilterCompareResult.IsMatch);
|
||||
}
|
||||
|
||||
static void CompareAndAssert(string topic, string filter, MqttTopicFilterCompareResult expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, MqttTopicFilterComparer.Compare(topic, filter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace MQTTnet.TestApp.NetCore
|
||||
|
||||
ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(context =>
|
||||
{
|
||||
if (MqttTopicFilterComparer.IsMatch(context.ApplicationMessage.Topic, "/myTopic/WithTimestamp/#"))
|
||||
if (MqttTopicFilterComparer.Compare(context.ApplicationMessage.Topic, "/myTopic/WithTimestamp/#") == MqttTopicFilterCompareResult.IsMatch)
|
||||
{
|
||||
// Replace the payload with the timestamp. But also extending a JSON
|
||||
// based payload with the timestamp is a suitable use case.
|
||||
|
||||
Reference in New Issue
Block a user