mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-19 02:53:06 +08:00
Feature/mqttv5 subscriptions server (#1246)
* Add support for RetainHandling. * Add support for No Local. * Add support for _SubscriptionIdentifier_. * Add more Unit Tests. * Update docs.
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Assigned_Client_ID_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public Task Connect_With_No_Client_Id()
|
||||
{
|
||||
return Connect_With_Client_Id("test_123", "test_123", null, "test_123");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public Task Connect_With_Client_Id()
|
||||
{
|
||||
return Connect_With_Client_Id("Connect_With_Client_Idtest_456", null, "test_456", null);
|
||||
}
|
||||
|
||||
async Task Connect_With_Client_Id(string expectedClientId, string expectedReturnedClientId, string usedClientId, string assignedClientId)
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
string serverConnectedClientId = null;
|
||||
string serverDisconnectedClientId = null;
|
||||
string clientAssignedClientId = null;
|
||||
|
||||
// Arrange server
|
||||
var disconnectedMre = new ManualResetEventSlim();
|
||||
var serverOptions = new MqttServerOptionsBuilder()
|
||||
.WithConnectionValidator(context =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(context.ClientId))
|
||||
{
|
||||
context.AssignedClientIdentifier = assignedClientId;
|
||||
context.ReasonCode = MqttConnectReasonCode.Success;
|
||||
}
|
||||
});
|
||||
|
||||
await testEnvironment.StartServer(serverOptions);
|
||||
testEnvironment.Server.UseClientConnectedHandler(args =>
|
||||
{
|
||||
serverConnectedClientId = args.ClientId;
|
||||
});
|
||||
|
||||
testEnvironment.Server.UseClientDisconnectedHandler(args =>
|
||||
{
|
||||
serverDisconnectedClientId = args.ClientId;
|
||||
disconnectedMre.Set();
|
||||
});
|
||||
|
||||
// Arrange client
|
||||
var client = testEnvironment.CreateClient();
|
||||
client.UseConnectedHandler(args =>
|
||||
{
|
||||
clientAssignedClientId = args.ConnectResult.AssignedClientIdentifier;
|
||||
});
|
||||
|
||||
// Act
|
||||
await client.ConnectAsync(new MqttClientOptionsBuilder()
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
|
||||
.WithProtocolVersion(MqttProtocolVersion.V500)
|
||||
.WithClientId(usedClientId)
|
||||
.Build());
|
||||
|
||||
await client.DisconnectAsync();
|
||||
|
||||
// Wait for ClientDisconnectedHandler to trigger
|
||||
disconnectedMre.Wait(1000);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(expectedClientId, serverConnectedClientId);
|
||||
Assert.AreEqual(expectedClientId, serverDisconnectedClientId);
|
||||
Assert.AreEqual(expectedReturnedClientId, clientAssignedClientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Implementations;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Connection_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Close_Idle_Connection_On_Connect()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithDefaultCommunicationTimeout(TimeSpan.FromSeconds(1)));
|
||||
|
||||
var client = new CrossPlatformSocket(AddressFamily.InterNetwork);
|
||||
await client.ConnectAsync("localhost", testEnvironment.ServerPort, CancellationToken.None);
|
||||
|
||||
// Don't send anything. The server should close the connection.
|
||||
await Task.Delay(TimeSpan.FromSeconds(3));
|
||||
|
||||
try
|
||||
{
|
||||
var receivedBytes = await client.ReceiveAsync(new ArraySegment<byte>(new byte[10]), SocketFlags.Partial);
|
||||
if (receivedBytes == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.Fail("Receive should throw an exception.");
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Send_Garbage()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithDefaultCommunicationTimeout(TimeSpan.FromSeconds(1)));
|
||||
|
||||
// Send an invalid packet and ensure that the server will close the connection and stay in a waiting state
|
||||
// forever. This is security related.
|
||||
var client = new CrossPlatformSocket(AddressFamily.InterNetwork);
|
||||
await client.ConnectAsync("localhost", testEnvironment.ServerPort, CancellationToken.None);
|
||||
|
||||
var buffer = Encoding.UTF8.GetBytes("Garbage");
|
||||
await client.SendAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
|
||||
|
||||
await Task.Delay(TimeSpan.FromSeconds(3));
|
||||
|
||||
try
|
||||
{
|
||||
var receivedBytes = await client.ReceiveAsync(new ArraySegment<byte>(new byte[10]), SocketFlags.Partial);
|
||||
if (receivedBytes == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.Fail("Receive should throw an exception.");
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Receiving;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Events_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Fire_Client_Connected_Event()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
MqttServerClientConnectedEventArgs eventArgs = null;
|
||||
server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
|
||||
await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser"));
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
Assert.IsNotNull(eventArgs);
|
||||
|
||||
Assert.IsTrue(eventArgs.ClientId.StartsWith(nameof(Fire_Client_Connected_Event)));
|
||||
Assert.IsTrue(eventArgs.Endpoint.Contains("127.0.0.1"));
|
||||
Assert.AreEqual(MqttProtocolVersion.V311, eventArgs.ProtocolVersion);
|
||||
Assert.AreEqual("TheUser", eventArgs.UserName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Fire_Client_Disconnected_Event()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
MqttServerClientDisconnectedEventArgs eventArgs = null;
|
||||
server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
|
||||
var client = await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser"));
|
||||
await client.DisconnectAsync();
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
Assert.IsNotNull(eventArgs);
|
||||
|
||||
Assert.IsTrue(eventArgs.ClientId.StartsWith(nameof(Fire_Client_Disconnected_Event)));
|
||||
Assert.IsTrue(eventArgs.Endpoint.Contains("127.0.0.1"));
|
||||
Assert.AreEqual(MqttClientDisconnectType.Clean, eventArgs.DisconnectType);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Fire_Client_Subscribed_Event()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
MqttServerClientSubscribedTopicEventArgs eventArgs = null;
|
||||
server.ClientSubscribedTopicHandler = new MqttServerClientSubscribedTopicHandlerDelegate(e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
await client.SubscribeAsync("The/Topic", MqttQualityOfServiceLevel.AtLeastOnce);
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
Assert.IsNotNull(eventArgs);
|
||||
|
||||
Assert.IsTrue(eventArgs.ClientId.StartsWith(nameof(Fire_Client_Subscribed_Event)));
|
||||
Assert.AreEqual("The/Topic", eventArgs.TopicFilter.Topic);
|
||||
Assert.AreEqual(MqttQualityOfServiceLevel.AtLeastOnce, eventArgs.TopicFilter.QualityOfServiceLevel);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Fire_Client_Unsubscribed_Event()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
MqttServerClientUnsubscribedTopicEventArgs eventArgs = null;
|
||||
server.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
await client.UnsubscribeAsync("The/Topic");
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
Assert.IsNotNull(eventArgs);
|
||||
|
||||
Assert.IsTrue(eventArgs.ClientId.StartsWith(nameof(Fire_Client_Unsubscribed_Event)));
|
||||
Assert.AreEqual("The/Topic", eventArgs.TopicFilter);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Fire_Application_Message_Received_Event()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
MqttApplicationMessageReceivedEventArgs eventArgs = null;
|
||||
server.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
await client.PublishAsync("The_Topic", "The_Payload");
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
Assert.IsNotNull(eventArgs);
|
||||
|
||||
Assert.IsTrue(eventArgs.ClientId.StartsWith(nameof(Fire_Application_Message_Received_Event)));
|
||||
Assert.AreEqual("The_Topic", eventArgs.ApplicationMessage.Topic);
|
||||
Assert.AreEqual("The_Payload", eventArgs.ApplicationMessage.ConvertPayloadToString());
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Fire_Started_Event()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var server = testEnvironment.CreateServer();
|
||||
|
||||
EventArgs eventArgs = null;
|
||||
server.StartedHandler = new MqttServerStartedHandlerDelegate(e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
|
||||
await server.StartAsync(new MqttServerOptionsBuilder().Build());
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
Assert.IsNotNull(eventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Fire_Stopped_Event()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
EventArgs eventArgs = null;
|
||||
server.StoppedHandler = new MqttServerStoppedHandlerDelegate(e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
|
||||
await server.StopAsync();
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
Assert.IsNotNull(eventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class KeepAlive_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Disconnect_Client_DueTo_KeepAlive()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client = await testEnvironment.ConnectLowLevelClient(o => o
|
||||
.WithCommunicationTimeout(TimeSpan.FromSeconds(1))
|
||||
.WithCommunicationTimeout(TimeSpan.Zero)
|
||||
.WithProtocolVersion(MqttProtocolVersion.V500)).ConfigureAwait(false);
|
||||
|
||||
await client.SendAsync(new MqttConnectPacket
|
||||
{
|
||||
CleanSession = true,
|
||||
ClientId = "Disconnect_Client_DueTo_KeepAlive",
|
||||
KeepAlivePeriod = 1
|
||||
}, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
var responsePacket = await client.ReceiveAsync(CancellationToken.None).ConfigureAwait(false);
|
||||
Assert.IsTrue(responsePacket is MqttConnAckPacket);
|
||||
|
||||
for (var i = 0; i < 6; i++)
|
||||
{
|
||||
await Task.Delay(500);
|
||||
|
||||
await client.SendAsync(MqttPingReqPacket.Instance, CancellationToken.None);
|
||||
responsePacket = await client.ReceiveAsync(CancellationToken.None);
|
||||
Assert.IsTrue(responsePacket is MqttPingRespPacket);
|
||||
}
|
||||
|
||||
// If we reach this point everything works as expected (server did not close the connection
|
||||
// due to proper ping messages.
|
||||
// Now we will wait 1.1 seconds because the server MUST wait 1.5 seconds in total (See spec).
|
||||
|
||||
await Task.Delay(1100);
|
||||
await client.SendAsync(MqttPingReqPacket.Instance, CancellationToken.None);
|
||||
responsePacket = await client.ReceiveAsync(CancellationToken.None);
|
||||
Assert.IsTrue(responsePacket is MqttPingRespPacket);
|
||||
|
||||
// Now we will wait longer than 1.5 so that the server will close the connection.
|
||||
responsePacket = await client.ReceiveAsync(CancellationToken.None);
|
||||
|
||||
var disconnectPacket = responsePacket as MqttDisconnectPacket;
|
||||
|
||||
Assert.IsTrue(disconnectPacket != null);
|
||||
Assert.AreEqual(disconnectPacket.ReasonCode, MqttDisconnectReasonCode.KeepAliveTimeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
using MQTTnet.Server.Internal;
|
||||
using MQTTnet.Tests.Mockups;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public class MqttSubscriptionsManager_Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task MqttSubscriptionsManager_SubscribeSingleSuccess()
|
||||
{
|
||||
var s = CreateSession();
|
||||
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventDispatcher(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||
|
||||
await sm.Subscribe(sp);
|
||||
|
||||
var result = sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce, "");
|
||||
Assert.IsTrue(result.IsSubscribed);
|
||||
Assert.AreEqual(result.QualityOfServiceLevel, MqttQualityOfServiceLevel.AtMostOnce);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttSubscriptionsManager_SubscribeDifferentQoSSuccess()
|
||||
{
|
||||
var s = CreateSession();
|
||||
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventDispatcher(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new MqttTopicFilter { Topic = "A/B/C", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
|
||||
|
||||
await sm.Subscribe(sp);
|
||||
|
||||
var result = sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.ExactlyOnce, "");
|
||||
Assert.IsTrue(result.IsSubscribed);
|
||||
Assert.AreEqual(result.QualityOfServiceLevel, MqttQualityOfServiceLevel.AtMostOnce);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttSubscriptionsManager_SubscribeTwoTimesSuccess()
|
||||
{
|
||||
var s = CreateSession();
|
||||
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventDispatcher(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new MqttTopicFilter { Topic = "#", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
|
||||
sp.TopicFilters.Add(new MqttTopicFilter { Topic = "A/B/C", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
|
||||
|
||||
await sm.Subscribe(sp);
|
||||
|
||||
var result = sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.ExactlyOnce, "");
|
||||
Assert.IsTrue(result.IsSubscribed);
|
||||
Assert.AreEqual(result.QualityOfServiceLevel, MqttQualityOfServiceLevel.AtLeastOnce);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttSubscriptionsManager_SubscribeSingleNoSuccess()
|
||||
{
|
||||
var s = CreateSession();
|
||||
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventDispatcher(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||
|
||||
await sm.Subscribe(sp);
|
||||
|
||||
Assert.IsFalse(sm.CheckSubscriptions("A/B/X", MqttQualityOfServiceLevel.AtMostOnce, "").IsSubscribed);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttSubscriptionsManager_SubscribeAndUnsubscribeSingle()
|
||||
{
|
||||
var s = CreateSession();
|
||||
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventDispatcher(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||
|
||||
await sm.Subscribe(sp);
|
||||
|
||||
Assert.IsTrue(sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce, "").IsSubscribed);
|
||||
|
||||
var up = new MqttUnsubscribePacket();
|
||||
up.TopicFilters.Add("A/B/C");
|
||||
await sm.Unsubscribe(up);
|
||||
|
||||
Assert.IsFalse(sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce, "").IsSubscribed);
|
||||
}
|
||||
|
||||
MqttClientSession CreateSession()
|
||||
{
|
||||
return new MqttClientSession(
|
||||
"",
|
||||
new ConcurrentDictionary<object, object>(),
|
||||
new MqttServerEventDispatcher(new TestLogger()),
|
||||
new MqttServerOptions(),
|
||||
new MqttRetainedMessagesManager());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class No_Local_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public Task Subscribe_With_No_Local()
|
||||
{
|
||||
return ExecuteTest(true, 0);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public Task Subscribe_Without_No_Local()
|
||||
{
|
||||
return ExecuteTest(false, 1);
|
||||
}
|
||||
|
||||
async Task ExecuteTest(
|
||||
bool noLocal,
|
||||
int expectedCountAfterPublish)
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client1 = await testEnvironment.ConnectClient();
|
||||
var applicationMessageHandler = testEnvironment.CreateApplicationMessageHandler(client1);
|
||||
var topicFilter = testEnvironment.Factory.CreateTopicFilterBuilder().WithTopic("Topic").WithNoLocal(noLocal).Build();
|
||||
await client1.SubscribeAsync(topicFilter);
|
||||
await LongTestDelay();
|
||||
|
||||
applicationMessageHandler.AssertReceivedCountEquals(0);
|
||||
|
||||
// The client will publish a message where it is itself subscribing to.
|
||||
await client1.PublishAsync("Topic", "Payload", true);
|
||||
await LongTestDelay();
|
||||
|
||||
applicationMessageHandler.AssertReceivedCountEquals(expectedCountAfterPublish);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Client;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Retain_As_Published_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public Task Subscribe_With_Retain_As_Published()
|
||||
{
|
||||
return ExecuteTest(true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public Task Subscribe_Without_Retain_As_Published()
|
||||
{
|
||||
return ExecuteTest(false);
|
||||
}
|
||||
|
||||
async Task ExecuteTest(bool retainAsPublished)
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client1 = await testEnvironment.ConnectClient();
|
||||
var applicationMessageHandler = testEnvironment.CreateApplicationMessageHandler(client1);
|
||||
var topicFilter = testEnvironment.Factory.CreateTopicFilterBuilder().WithTopic("Topic").WithRetainAsPublished(retainAsPublished).Build();
|
||||
await client1.SubscribeAsync(topicFilter);
|
||||
await LongTestDelay();
|
||||
|
||||
// The client will publish a message where it is itself subscribing to.
|
||||
await client1.PublishAsync("Topic", "Payload", true);
|
||||
await LongTestDelay();
|
||||
|
||||
applicationMessageHandler.AssertReceivedCountEquals(1);
|
||||
Assert.AreEqual(retainAsPublished, applicationMessageHandler.ReceivedApplicationMessages[0].Retain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Retain_Handling_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public Task Send_At_Subscribe()
|
||||
{
|
||||
return ExecuteTest(MqttRetainHandling.SendAtSubscribe, 1, 2, 3);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public Task Do_Not_Send_On_Subscribe()
|
||||
{
|
||||
return ExecuteTest(MqttRetainHandling.DoNotSendOnSubscribe, 0, 1, 1);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public Task Send_At_Subscribe_If_New_Subscription_Only()
|
||||
{
|
||||
return ExecuteTest(MqttRetainHandling.SendAtSubscribeIfNewSubscriptionOnly, 1, 2, 2);
|
||||
}
|
||||
|
||||
async Task ExecuteTest(
|
||||
MqttRetainHandling retainHandling,
|
||||
int expectedCountAfterSubscribe,
|
||||
int expectedCountAfterSecondPublish,
|
||||
int expectedCountAfterSecondSubscribe)
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client1 = await testEnvironment.ConnectClient();
|
||||
await client1.PublishAsync("Topic", "Payload", true);
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
var client2 = await testEnvironment.ConnectClient();
|
||||
var applicationMessageHandler = testEnvironment.CreateApplicationMessageHandler(client2);
|
||||
|
||||
var topicFilter = testEnvironment.Factory.CreateTopicFilterBuilder().WithTopic("Topic").WithRetainHandling(retainHandling).Build();
|
||||
await client2.SubscribeAsync(topicFilter);
|
||||
await LongTestDelay();
|
||||
|
||||
applicationMessageHandler.AssertReceivedCountEquals(expectedCountAfterSubscribe);
|
||||
|
||||
await client1.PublishAsync("Topic", "Payload", true);
|
||||
await LongTestDelay();
|
||||
|
||||
applicationMessageHandler.AssertReceivedCountEquals(expectedCountAfterSecondPublish);
|
||||
|
||||
await client2.SubscribeAsync(topicFilter);
|
||||
await LongTestDelay();
|
||||
|
||||
applicationMessageHandler.AssertReceivedCountEquals(expectedCountAfterSecondSubscribe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Retained_Messages_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Server_Reports_Retained_Messages_Supported_V3()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client = testEnvironment.CreateClient();
|
||||
var connectResult = await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
|
||||
.WithProtocolVersion(MqttProtocolVersion.V311)
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
|
||||
|
||||
Assert.IsTrue(connectResult.RetainAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Server_Reports_Retained_Messages_Supported_V5()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client = testEnvironment.CreateClient();
|
||||
var connectResult = await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
|
||||
.WithProtocolVersion(MqttProtocolVersion.V500)
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
|
||||
|
||||
Assert.IsTrue(connectResult.RetainAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Retained_Messages_Flow()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var retainedMessage = new MqttApplicationMessageBuilder().WithTopic("r").WithPayload("r").WithRetainFlag().Build();
|
||||
|
||||
await testEnvironment.StartServer();
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
|
||||
|
||||
await c1.PublishAsync(retainedMessage);
|
||||
await c1.DisconnectAsync();
|
||||
await LongTestDelay();
|
||||
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
await c2.UnsubscribeAsync("r");
|
||||
await Task.Delay(100);
|
||||
messageHandler.AssertReceivedCountEquals(i);
|
||||
|
||||
await c2.SubscribeAsync("r");
|
||||
await Task.Delay(100);
|
||||
messageHandler.AssertReceivedCountEquals(i + 1);
|
||||
}
|
||||
|
||||
await c2.DisconnectAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Receive_No_Retained_Message_After_Subscribe()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
|
||||
await c1.DisconnectAsync();
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
|
||||
await c2.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("retained_other").Build());
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
messageHandler.AssertReceivedCountEquals(0);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Receive_Retained_Message_After_Subscribe()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
|
||||
await c1.DisconnectAsync();
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
|
||||
|
||||
await c2.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("retained").Build());
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
messageHandler.AssertReceivedCountEquals(1);
|
||||
Assert.IsTrue(messageHandler.ReceivedApplicationMessages.First().Retain);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Clear_Retained_Message_With_Empty_Payload()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
|
||||
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
|
||||
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[0]).WithRetainFlag().Build());
|
||||
|
||||
await c1.DisconnectAsync();
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
|
||||
|
||||
await Task.Delay(200);
|
||||
await c2.SubscribeAsync(new MqttTopicFilter { Topic = "retained", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
|
||||
await Task.Delay(500);
|
||||
|
||||
messageHandler.AssertReceivedCountEquals(0);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Clear_Retained_Message_With_Null_Payload()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
|
||||
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
|
||||
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload((byte[])null).WithRetainFlag().Build());
|
||||
|
||||
await c1.DisconnectAsync();
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
|
||||
|
||||
await Task.Delay(200);
|
||||
await c2.SubscribeAsync(new MqttTopicFilter { Topic = "retained", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
|
||||
await Task.Delay(500);
|
||||
|
||||
messageHandler.AssertReceivedCountEquals(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Security_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Use_Username_Null_Password_Empty()
|
||||
{
|
||||
string username = null;
|
||||
var password = string.Empty;
|
||||
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
testEnvironment.IgnoreClientLogErrors = true;
|
||||
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client = testEnvironment.CreateClient();
|
||||
|
||||
var clientOptions = new MqttClientOptionsBuilder()
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
|
||||
.WithCredentials(username, password)
|
||||
.Build();
|
||||
|
||||
var ex = await Assert.ThrowsExceptionAsync<MqttConnectingFailedException>(async () => await client.ConnectAsync(clientOptions));
|
||||
Assert.IsInstanceOfType(ex.InnerException, typeof(MqttProtocolViolationException));
|
||||
Assert.AreEqual("Error while authenticating. If the User Name Flag is set to 0, the Password Flag MUST be set to 0 [MQTT-3.1.2-22].", ex.Message, false);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public Task Handle_Wrong_UserName()
|
||||
{
|
||||
return TestCredentials("x", "Password1");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public Task Handle_Wrong_Password()
|
||||
{
|
||||
return TestCredentials("UserName", "x");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public Task Handle_Wrong_UserName_And_Password()
|
||||
{
|
||||
return TestCredentials("x", "x");
|
||||
}
|
||||
|
||||
async Task TestCredentials(string userName, string password)
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
testEnvironment.IgnoreClientLogErrors = true;
|
||||
|
||||
await testEnvironment.StartServer(testEnvironment.Factory.CreateServerOptionsBuilder()
|
||||
.WithConnectionValidator(c =>
|
||||
{
|
||||
if (c.Username != "UserName1")
|
||||
{
|
||||
c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
|
||||
}
|
||||
|
||||
if (c.Password != "Password1")
|
||||
{
|
||||
c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
|
||||
}
|
||||
}));
|
||||
|
||||
var client = testEnvironment.CreateClient();
|
||||
|
||||
var clientOptions = new MqttClientOptionsBuilder()
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
|
||||
.WithCredentials(userName, password)
|
||||
.Build();
|
||||
|
||||
var ex = await Assert.ThrowsExceptionAsync<MqttConnectingFailedException>(async () => await client.ConnectAsync(clientOptions));
|
||||
Assert.AreEqual(ex.Result.ResultCode, MqttClientConnectResultCode.BadUserNameOrPassword);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Server_Reference_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Server_Reports_With_Reference_Server()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
testEnvironment.IgnoreClientLogErrors = true;
|
||||
|
||||
await testEnvironment.StartServer(o =>
|
||||
{
|
||||
o.WithConnectionValidator(v =>
|
||||
{
|
||||
v.ReasonCode = MqttConnectReasonCode.ServerMoved;
|
||||
v.ServerReference = "new_server";
|
||||
});
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
var client = testEnvironment.CreateClient();
|
||||
|
||||
await client.ConnectAsync(new MqttClientOptionsBuilder()
|
||||
.WithProtocolVersion(MqttProtocolVersion.V500)
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
|
||||
.Build());
|
||||
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (MqttConnectingFailedException e)
|
||||
{
|
||||
Assert.AreEqual(MqttClientConnectResultCode.ServerMoved, e.ResultCode);
|
||||
Assert.AreEqual("new_server", e.Result.ServerReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Client.Subscribing;
|
||||
using MQTTnet.Server;
|
||||
using MQTTnet.Tests.Mockups;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public class Session_Tests
|
||||
{
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
[TestMethod]
|
||||
public async Task Set_Session_Item()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var serverOptions = new MqttServerOptionsBuilder()
|
||||
.WithConnectionValidator(delegate (MqttConnectionValidatorContext context)
|
||||
{
|
||||
// Don't validate anything. Just set some session items.
|
||||
context.SessionItems["can_subscribe_x"] = true;
|
||||
context.SessionItems["default_payload"] = "Hello World";
|
||||
})
|
||||
.WithSubscriptionInterceptor(delegate (MqttSubscriptionInterceptorContext context)
|
||||
{
|
||||
if (context.TopicFilter.Topic == "x")
|
||||
{
|
||||
context.AcceptSubscription = context.SessionItems["can_subscribe_x"] as bool? == true;
|
||||
}
|
||||
})
|
||||
.WithApplicationMessageInterceptor(delegate (MqttApplicationMessageInterceptorContext context)
|
||||
{
|
||||
context.ApplicationMessage.Payload = Encoding.UTF8.GetBytes(context.SessionItems["default_payload"] as string);
|
||||
});
|
||||
|
||||
await testEnvironment.StartServer(serverOptions);
|
||||
|
||||
string receivedPayload = null;
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
client.UseApplicationMessageReceivedHandler(delegate (MqttApplicationMessageReceivedEventArgs args)
|
||||
{
|
||||
receivedPayload = args.ApplicationMessage.ConvertPayloadToString();
|
||||
});
|
||||
|
||||
var subscribeResult = await client.SubscribeAsync("x");
|
||||
|
||||
Assert.AreEqual(MqttClientSubscribeResultCode.GrantedQoS0, subscribeResult.Items[0].ResultCode);
|
||||
|
||||
var client2 = await testEnvironment.ConnectClient();
|
||||
await client2.PublishAsync("x");
|
||||
|
||||
await Task.Delay(1000);
|
||||
|
||||
Assert.AreEqual("Hello World", receivedPayload);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Get_Session_Items_In_Status()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var serverOptions = new MqttServerOptionsBuilder()
|
||||
.WithConnectionValidator(delegate (MqttConnectionValidatorContext context)
|
||||
{
|
||||
// Don't validate anything. Just set some session items.
|
||||
context.SessionItems["can_subscribe_x"] = true;
|
||||
context.SessionItems["default_payload"] = "Hello World";
|
||||
});
|
||||
|
||||
await testEnvironment.StartServer(serverOptions);
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
|
||||
var sessionStatus = await testEnvironment.Server.GetSessionStatusAsync();
|
||||
var session = sessionStatus.First();
|
||||
|
||||
Assert.AreEqual(true, session.Items["can_subscribe_x"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public async Task Manage_Session_MaxParallel()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
testEnvironment.IgnoreClientLogErrors = true;
|
||||
var serverOptions = new MqttServerOptionsBuilder();
|
||||
await testEnvironment.StartServer(serverOptions);
|
||||
|
||||
var options = new MqttClientOptionsBuilder().WithClientId("1");
|
||||
|
||||
var clients = await Task.WhenAll(Enumerable.Range(0, 10)
|
||||
.Select(i => TryConnect(testEnvironment, options)));
|
||||
|
||||
var connectedClients = clients.Where(c => c?.IsConnected ?? false).ToList();
|
||||
|
||||
Assert.AreEqual(1, connectedClients.Count);
|
||||
}
|
||||
}
|
||||
|
||||
async Task<IMqttClient> TryConnect(TestEnvironment testEnvironment, MqttClientOptionsBuilder options)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await testEnvironment.ConnectClient(options);
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Shared_Subscriptions_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Server_Reports_Shared_Subscriptions_Not_Supported()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client = testEnvironment.CreateClient();
|
||||
var connectResult = await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
|
||||
.WithProtocolVersion(MqttProtocolVersion.V500)
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
|
||||
|
||||
Assert.IsFalse(connectResult.SharedSubscriptionAvailable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
using MQTTnet.Tests.Mockups;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Status_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Show_Client_And_Session_Statistics()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("client1"));
|
||||
var c2 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("client2"));
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
var clientStatus = await server.GetClientStatusAsync();
|
||||
var sessionStatus = await server.GetSessionStatusAsync();
|
||||
|
||||
Assert.AreEqual(2, clientStatus.Count);
|
||||
Assert.AreEqual(2, sessionStatus.Count);
|
||||
|
||||
Assert.IsTrue(clientStatus.Any(s => s.ClientId == c1.Options.ClientId));
|
||||
Assert.IsTrue(clientStatus.Any(s => s.ClientId == c2.Options.ClientId));
|
||||
|
||||
await c1.DisconnectAsync();
|
||||
await c2.DisconnectAsync();
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
clientStatus = await server.GetClientStatusAsync();
|
||||
sessionStatus = await server.GetSessionStatusAsync();
|
||||
|
||||
Assert.AreEqual(0, clientStatus.Count);
|
||||
Assert.AreEqual(0, sessionStatus.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Disconnect_Client()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("client1"));
|
||||
|
||||
await Task.Delay(1000);
|
||||
|
||||
var clientStatus = await server.GetClientStatusAsync();
|
||||
|
||||
Assert.AreEqual(1, clientStatus.Count);
|
||||
Assert.IsTrue(clientStatus.Any(s => s.ClientId == c1.Options.ClientId));
|
||||
|
||||
await clientStatus.First().DisconnectAsync();
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.IsFalse(c1.IsConnected);
|
||||
|
||||
clientStatus = await server.GetClientStatusAsync();
|
||||
|
||||
Assert.AreEqual(0, clientStatus.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Keep_Persistent_Session()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var server = await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithPersistentSessions());
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("client1"));
|
||||
var c2 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("client2"));
|
||||
|
||||
await c1.DisconnectAsync();
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
var clientStatus = await server.GetClientStatusAsync();
|
||||
var sessionStatus = await server.GetSessionStatusAsync();
|
||||
|
||||
Assert.AreEqual(1, clientStatus.Count);
|
||||
Assert.AreEqual(2, sessionStatus.Count);
|
||||
|
||||
await c2.DisconnectAsync();
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
clientStatus = await server.GetClientStatusAsync();
|
||||
sessionStatus = await server.GetSessionStatusAsync();
|
||||
|
||||
Assert.AreEqual(0, clientStatus.Count);
|
||||
Assert.AreEqual(2, sessionStatus.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Track_Sent_Application_Messages()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var server = await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithPersistentSessions());
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
|
||||
for (var i = 1; i < 25; i++)
|
||||
{
|
||||
await c1.PublishAsync("a");
|
||||
await Task.Delay(50);
|
||||
|
||||
var clientStatus = await server.GetClientStatusAsync();
|
||||
Assert.AreEqual(i, clientStatus.First().SentApplicationMessagesCount);
|
||||
Assert.AreEqual(0, clientStatus.First().ReceivedApplicationMessagesCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Track_Sent_Packets()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
var server = await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithPersistentSessions());
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithNoKeepAlive());
|
||||
|
||||
for (var i = 1; i < 25; i++)
|
||||
{
|
||||
// At most once will send one packet to the client and the server will reply
|
||||
// with an additional ACK packet.
|
||||
await c1.PublishAsync("a", string.Empty, MqttQualityOfServiceLevel.AtLeastOnce);
|
||||
await Task.Delay(250);
|
||||
|
||||
var clientStatus = await server.GetClientStatusAsync();
|
||||
|
||||
Assert.AreEqual(i, clientStatus.First().SentApplicationMessagesCount, "SAMC invalid!");
|
||||
|
||||
// + 1 because CONNECT is also counted.
|
||||
Assert.AreEqual(i + 1, clientStatus.First().SentPacketsCount, "SPC invalid!");
|
||||
|
||||
// +1 because ConnACK package is already counted.
|
||||
Assert.AreEqual(i + 1, clientStatus.First().ReceivedPacketsCount, "RPC invalid!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Subscription_Identifier_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Server_Reports_Subscription_Identifiers_Supported()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client = testEnvironment.CreateClient();
|
||||
var connectResult = await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
|
||||
.WithProtocolVersion(MqttProtocolVersion.V500)
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
|
||||
|
||||
Assert.IsTrue(connectResult.SubscriptionIdentifiersAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_With_Subscription_Identifier()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client1 = await testEnvironment.ConnectClient();
|
||||
var applicationMessageHandler = testEnvironment.CreateApplicationMessageHandler(client1);
|
||||
var topicFilter = testEnvironment.Factory.CreateTopicFilterBuilder().WithTopic("Topic").Build();
|
||||
var subscribeOptions = testEnvironment.Factory.CreateSubscribeOptionsBuilder().WithSubscriptionIdentifier(456).WithTopicFilter(topicFilter).Build();
|
||||
|
||||
await client1.SubscribeAsync(subscribeOptions);
|
||||
await LongTestDelay();
|
||||
|
||||
applicationMessageHandler.AssertReceivedCountEquals(0);
|
||||
|
||||
// The client will publish a message where it is itself subscribing to.
|
||||
await client1.PublishAsync("Topic", "Payload", true);
|
||||
await LongTestDelay();
|
||||
|
||||
applicationMessageHandler.AssertReceivedCountEquals(1);
|
||||
|
||||
applicationMessageHandler.ReceivedApplicationMessages[0].SubscriptionIdentifiers.Contains(456);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Subscribe_With_Multiple_Subscription_Identifiers()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client1 = await testEnvironment.ConnectClient();
|
||||
var applicationMessageHandler = testEnvironment.CreateApplicationMessageHandler(client1);
|
||||
|
||||
var topicFilter = testEnvironment.Factory.CreateTopicFilterBuilder().WithTopic("Topic/A").Build();
|
||||
var subscribeOptions = testEnvironment.Factory.CreateSubscribeOptionsBuilder().WithSubscriptionIdentifier(456).WithTopicFilter(topicFilter).Build();
|
||||
await client1.SubscribeAsync(subscribeOptions);
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
topicFilter = testEnvironment.Factory.CreateTopicFilterBuilder().WithTopic("Topic/+").Build();
|
||||
subscribeOptions = testEnvironment.Factory.CreateSubscribeOptionsBuilder().WithSubscriptionIdentifier(789).WithTopicFilter(topicFilter).Build();
|
||||
await client1.SubscribeAsync(subscribeOptions);
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
applicationMessageHandler.AssertReceivedCountEquals(0);
|
||||
|
||||
// The client will publish a message where it is itself subscribing to.
|
||||
await client1.PublishAsync("Topic/A", "Payload", true);
|
||||
await LongTestDelay();
|
||||
|
||||
applicationMessageHandler.AssertReceivedCountEquals(1);
|
||||
|
||||
applicationMessageHandler.ReceivedApplicationMessages[0].SubscriptionIdentifiers.Contains(456);
|
||||
applicationMessageHandler.ReceivedApplicationMessages[0].SubscriptionIdentifiers.Contains(789);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Server.Internal;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public class TopicFilterComparer_Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_Plus_Match_With_Separator_Only()
|
||||
{
|
||||
//A Topic Name or Topic Filter consisting only of the ‘/’ character is valid
|
||||
CompareAndAssert("A", "+", true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_Hash_Match_With_Separator_Only()
|
||||
{
|
||||
//A Topic Name or Topic Filter consisting only of the ‘/’ character is valid
|
||||
CompareAndAssert("/", "#", true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_DirectMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C", "A/B/C", true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_DirectNoMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/X", "A/B/C", false);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_MiddleOneLevelWildcardMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C", "A/+/C", true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_MiddleOneLevelWildcardNoMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C/D", "A/+/C", false);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_BeginningOneLevelWildcardMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C", "+/B/C", true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_EndOneLevelWildcardMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C", "A/B/+", true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_EndMultipleLevelsWildcardMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C", "A/#", true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_EndMultipleLevelsWildcardNoMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C/D", "A/C/#", false);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_EndMultipleLevelsWildcardMatchEmptyLevel()
|
||||
{
|
||||
CompareAndAssert("A/", "A/#", true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_AllLevelsWildcardMatch()
|
||||
{
|
||||
CompareAndAssert("A/B/C/D", "#", true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_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/+", true);
|
||||
CompareAndAssert("sport/tennis/player2", "sport/tennis/+", true);
|
||||
CompareAndAssert("sport/tennis/player1/ranking", "sport/tennis/+", false);
|
||||
|
||||
CompareAndAssert("sport", "sport/#", true);
|
||||
CompareAndAssert("sport", "sport/+", false);
|
||||
CompareAndAssert("sport/", "sport/+", true);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TopicFilterComparer_SingleLevel_Finance()
|
||||
{
|
||||
// Tests from official MQTT spec (4.7.1.3 Single level wildcard)
|
||||
CompareAndAssert("/finance", "+/+", true);
|
||||
CompareAndAssert("/finance", "/+", true);
|
||||
CompareAndAssert("/finance", "+", false);
|
||||
}
|
||||
|
||||
private static void CompareAndAssert(string topic, string filter, bool expectedResult)
|
||||
{
|
||||
Assert.AreEqual(expectedResult, MqttTopicFilterComparer.IsMatch(topic, filter));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Topic_Alias_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Server_Reports_Topic_Alias_Supported()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client = testEnvironment.CreateClient();
|
||||
|
||||
var connectResult = await client.ConnectAsync(new MqttClientOptionsBuilder()
|
||||
.WithProtocolVersion(MqttProtocolVersion.V500)
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
|
||||
.Build());
|
||||
|
||||
Assert.AreEqual(connectResult.TopicAliasMaximum, ushort.MaxValue);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Publish_With_Topic_Alias()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var receivedTopics = new List<string>();
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient(options => options.WithProtocolVersion(MqttProtocolVersion.V500));
|
||||
c1.UseApplicationMessageReceivedHandler(e =>
|
||||
{
|
||||
lock (receivedTopics)
|
||||
{
|
||||
receivedTopics.Add(e.ApplicationMessage.Topic);
|
||||
}
|
||||
});
|
||||
|
||||
await c1.SubscribeAsync("#");
|
||||
|
||||
var c2 = await testEnvironment.ConnectClient(options => options.WithProtocolVersion(MqttProtocolVersion.V500));
|
||||
|
||||
var message = new MqttApplicationMessage
|
||||
{
|
||||
Topic = "this_is_the_topic",
|
||||
TopicAlias = 22
|
||||
};
|
||||
|
||||
await c2.PublishAsync(message);
|
||||
|
||||
message.Topic = null;
|
||||
|
||||
await c2.PublishAsync(message);
|
||||
await c2.PublishAsync(message);
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.AreEqual(3, receivedTopics.Count);
|
||||
CollectionAssert.AllItemsAreNotNull(receivedTopics);
|
||||
Assert.IsTrue(receivedTopics.All(t => t.Equals("this_is_the_topic")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Collections.Generic;
|
||||
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.Tests.Mockups;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public class Feature_Tests
|
||||
{
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
[TestMethod]
|
||||
public async Task Use_User_Properties()
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var sender = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500));
|
||||
var receiver = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500));
|
||||
|
||||
var message = new MqttApplicationMessageBuilder()
|
||||
.WithTopic("A")
|
||||
.WithUserProperty("x", "1")
|
||||
.WithUserProperty("y", "2")
|
||||
.WithUserProperty("z", "3")
|
||||
.WithUserProperty("z", "4"); // z is here two times to test list of items
|
||||
|
||||
await receiver.SubscribeAsync(new MqttClientSubscribeOptions
|
||||
{
|
||||
TopicFilters = new List<MqttTopicFilter>
|
||||
{
|
||||
new MqttTopicFilter { Topic = "#" }
|
||||
}
|
||||
}, CancellationToken.None);
|
||||
|
||||
MqttApplicationMessage receivedMessage = null;
|
||||
receiver.UseApplicationMessageReceivedHandler(e => receivedMessage = e.ApplicationMessage);
|
||||
|
||||
await sender.PublishAsync(message.Build(), CancellationToken.None);
|
||||
|
||||
await Task.Delay(1000);
|
||||
|
||||
Assert.IsNotNull(receivedMessage);
|
||||
Assert.AreEqual("A", receivedMessage.Topic);
|
||||
Assert.AreEqual(4, receivedMessage.UserProperties.Count);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class Wildcard_Subscription_Available_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Server_Reports_Wildcard_Subscription_Available_Tests_Supported_V3()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client = testEnvironment.CreateClient();
|
||||
var connectResult = await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
|
||||
.WithProtocolVersion(MqttProtocolVersion.V311)
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
|
||||
|
||||
Assert.IsTrue(connectResult.WildcardSubscriptionAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Server_Reports_Wildcard_Subscription_Available_Tests_Supported_V5()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
var client = testEnvironment.CreateClient();
|
||||
var connectResult = await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
|
||||
.WithProtocolVersion(MqttProtocolVersion.V500)
|
||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
|
||||
|
||||
Assert.IsTrue(connectResult.WildcardSubscriptionAvailable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user