mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-20 11:45:43 +08:00
Merge from develop.
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Internal;
|
||||
|
||||
namespace MQTTnet.Core.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class BlockingQueueTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void Preserve_Order()
|
||||
{
|
||||
var queue = new BlockingQueue<string>();
|
||||
queue.Enqueue("a");
|
||||
queue.Enqueue("b");
|
||||
queue.Enqueue("c");
|
||||
|
||||
Assert.AreEqual(3, queue.Count);
|
||||
|
||||
Assert.AreEqual("a", queue.Dequeue());
|
||||
Assert.AreEqual("b", queue.Dequeue());
|
||||
Assert.AreEqual("c", queue.Dequeue());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Remove_First_Items()
|
||||
{
|
||||
var queue = new BlockingQueue<string>();
|
||||
queue.Enqueue("a");
|
||||
queue.Enqueue("b");
|
||||
queue.Enqueue("c");
|
||||
|
||||
Assert.AreEqual("a", queue.RemoveFirst());
|
||||
Assert.AreEqual("b", queue.RemoveFirst());
|
||||
|
||||
Assert.AreEqual(1, queue.Count);
|
||||
|
||||
Assert.AreEqual("c", queue.Dequeue());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Clear_Items()
|
||||
{
|
||||
var queue = new BlockingQueue<string>();
|
||||
queue.Enqueue("a");
|
||||
queue.Enqueue("b");
|
||||
queue.Enqueue("c");
|
||||
|
||||
Assert.AreEqual(3, queue.Count);
|
||||
|
||||
queue.Clear();
|
||||
|
||||
Assert.AreEqual(0, queue.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Wait_For_Item()
|
||||
{
|
||||
var queue = new BlockingQueue<string>();
|
||||
|
||||
string item = null;
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
Task.Run(() =>
|
||||
{
|
||||
item = queue.Dequeue();
|
||||
});
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
Assert.AreEqual(0, queue.Count);
|
||||
Assert.AreEqual(null, item);
|
||||
|
||||
queue.Enqueue("x");
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
Assert.AreEqual("x", item);
|
||||
Assert.AreEqual(0, queue.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Wait_For_Times()
|
||||
{
|
||||
var number = 0;
|
||||
|
||||
var queue = new BlockingQueue<int>();
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
queue.Enqueue(1);
|
||||
await Task.Delay(100);
|
||||
}
|
||||
});
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
while (number < 50)
|
||||
{
|
||||
queue.Dequeue();
|
||||
Interlocked.Increment(ref number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,17 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<DebugType>Full</DebugType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.3.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.3.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj" />
|
||||
<ProjectReference Include="..\..\Source\MQTTnet\MQTTnet.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using MQTTnet.Extensions.ManagedClient;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Core.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class ManagedMqttClientTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Drop_New_Messages_On_Full_Queue()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var managedClient = factory.CreateManagedMqttClient();
|
||||
|
||||
var clientOptions = new ManagedMqttClientOptionsBuilder()
|
||||
.WithMaxPendingMessages(5)
|
||||
.WithPendingMessagesOverflowStrategy(MqttPendingMessagesOverflowStrategy.DropNewMessage);
|
||||
|
||||
clientOptions.WithClientOptions(o => o.WithTcpServer("localhost"));
|
||||
|
||||
await managedClient.StartAsync(clientOptions.Build());
|
||||
|
||||
await managedClient.PublishAsync(new MqttApplicationMessage { Topic = "1" });
|
||||
await managedClient.PublishAsync(new MqttApplicationMessage { Topic = "2" });
|
||||
await managedClient.PublishAsync(new MqttApplicationMessage { Topic = "3" });
|
||||
await managedClient.PublishAsync(new MqttApplicationMessage { Topic = "4" });
|
||||
await managedClient.PublishAsync(new MqttApplicationMessage { Topic = "5" });
|
||||
|
||||
await managedClient.PublishAsync(new MqttApplicationMessage { Topic = "6" });
|
||||
await managedClient.PublishAsync(new MqttApplicationMessage { Topic = "7" });
|
||||
await managedClient.PublishAsync(new MqttApplicationMessage { Topic = "8" });
|
||||
|
||||
Assert.AreEqual(5, managedClient.PendingApplicationMessagesCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,11 @@ using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Core.Tests
|
||||
@@ -97,11 +99,11 @@ namespace MQTTnet.Core.Tests
|
||||
c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
|
||||
|
||||
var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
|
||||
|
||||
|
||||
await c2.PublishAsync(message);
|
||||
await Task.Delay(1000);
|
||||
Assert.AreEqual(0, receivedMessagesCount);
|
||||
|
||||
|
||||
var subscribeEventCalled = false;
|
||||
s.ClientSubscribedTopic += (_, e) =>
|
||||
{
|
||||
@@ -115,7 +117,7 @@ namespace MQTTnet.Core.Tests
|
||||
await c2.PublishAsync(message);
|
||||
await Task.Delay(500);
|
||||
Assert.AreEqual(1, receivedMessagesCount);
|
||||
|
||||
|
||||
var unsubscribeEventCalled = false;
|
||||
s.ClientUnsubscribedTopic += (_, e) =>
|
||||
{
|
||||
@@ -233,7 +235,7 @@ namespace MQTTnet.Core.Tests
|
||||
await c1.PublishAsync(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttServer_ShutdownDisconnectsClientsGracefully()
|
||||
{
|
||||
@@ -302,6 +304,59 @@ namespace MQTTnet.Core.Tests
|
||||
Assert.AreEqual(clientConnectedCalled, clientDisconnectedCalled);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttServer_LotsOfRetainedMessages()
|
||||
{
|
||||
const int ClientCount = 100;
|
||||
|
||||
var server = new MqttFactory().CreateMqttServer();
|
||||
try
|
||||
{
|
||||
await server.StartAsync(new MqttServerOptionsBuilder().Build());
|
||||
|
||||
Parallel.For(
|
||||
0,
|
||||
ClientCount,
|
||||
new ParallelOptions { MaxDegreeOfParallelism = 10 },
|
||||
i =>
|
||||
{
|
||||
using (var client = new MqttFactory().CreateMqttClient())
|
||||
{
|
||||
client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build())
|
||||
.GetAwaiter().GetResult();
|
||||
|
||||
for (var j = 0; j < 10; j++)
|
||||
{
|
||||
// Clear retained message.
|
||||
client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("r" + i)
|
||||
.WithPayload(new byte[0]).WithRetainFlag().Build()).GetAwaiter().GetResult();
|
||||
|
||||
// Set retained message.
|
||||
client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("r" + i)
|
||||
.WithPayload("value" + j).WithRetainFlag().Build()).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
client.DisconnectAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
});
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
var retainedMessages = server.GetRetainedMessages();
|
||||
|
||||
Assert.AreEqual(ClientCount, retainedMessages.Count);
|
||||
|
||||
for (var i = 0; i < ClientCount; i++)
|
||||
{
|
||||
Assert.IsTrue(retainedMessages.Any(m => m.Topic == "r" + i));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
await server.StopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttServer_RetainedMessagesFlow()
|
||||
{
|
||||
@@ -552,6 +607,51 @@ namespace MQTTnet.Core.Tests
|
||||
Assert.IsTrue(bodyIsMatching);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttServer_ConnectionDenied()
|
||||
{
|
||||
var server = new MqttFactory().CreateMqttServer();
|
||||
var client = new MqttFactory().CreateMqttClient();
|
||||
|
||||
try
|
||||
{
|
||||
var options = new MqttServerOptionsBuilder().WithConnectionValidator(context =>
|
||||
{
|
||||
context.ReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized;
|
||||
}).Build();
|
||||
|
||||
await server.StartAsync(options);
|
||||
|
||||
|
||||
var clientOptions = new MqttClientOptionsBuilder()
|
||||
.WithTcpServer("localhost").Build();
|
||||
|
||||
try
|
||||
{
|
||||
await client.ConnectAsync(clientOptions);
|
||||
Assert.Fail("An exception should be raised.");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
if (exception is MqttConnectingFailedException)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Fail("Wrong exception.");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
await client.DisconnectAsync();
|
||||
await server.StopAsync();
|
||||
|
||||
client.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttServer_SameClientIdConnectDisconnectEventOrder()
|
||||
{
|
||||
@@ -600,6 +700,33 @@ namespace MQTTnet.Core.Tests
|
||||
Assert.IsFalse(connecteCalledBeforeConnectedClients, "ClientConnected was called before ClientDisconnect was called");
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public async Task MqttServer_StopAndRestart()
|
||||
{
|
||||
var server = new MqttFactory().CreateMqttServer();
|
||||
await server.StartAsync(new MqttServerOptions());
|
||||
|
||||
var client = new MqttFactory().CreateMqttClient();
|
||||
await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
|
||||
await server.StopAsync();
|
||||
|
||||
try
|
||||
{
|
||||
var client2 = new MqttFactory().CreateMqttClient();
|
||||
await client2.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
|
||||
|
||||
Assert.Fail("Connecting should fail.");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
await server.StartAsync(new MqttServerOptions());
|
||||
var client3 = new MqttFactory().CreateMqttClient();
|
||||
await client3.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
|
||||
}
|
||||
|
||||
private class TestStorage : IMqttServerStorage
|
||||
{
|
||||
public IList<MqttApplicationMessage> Messages = new List<MqttApplicationMessage>();
|
||||
@@ -623,25 +750,24 @@ namespace MQTTnet.Core.Tests
|
||||
MqttQualityOfServiceLevel filterQualityOfServiceLevel,
|
||||
int expectedReceivedMessagesCount)
|
||||
{
|
||||
var serverAdapter = new TestMqttServerAdapter();
|
||||
var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
|
||||
var s = new MqttFactory().CreateMqttServer();
|
||||
|
||||
var receivedMessagesCount = 0;
|
||||
try
|
||||
{
|
||||
await s.StartAsync(new MqttServerOptions());
|
||||
|
||||
var c1 = await serverAdapter.ConnectTestClient("c1");
|
||||
var c2 = await serverAdapter.ConnectTestClient("c2");
|
||||
|
||||
var c1 = new MqttFactory().CreateMqttClient();
|
||||
c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
|
||||
|
||||
await c1.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
|
||||
await c1.SubscribeAsync(new TopicFilterBuilder().WithTopic(topicFilter).WithQualityOfServiceLevel(filterQualityOfServiceLevel).Build());
|
||||
|
||||
var c2 = new MqttFactory().CreateMqttClient();
|
||||
await c2.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
|
||||
await c2.PublishAsync(builder => builder.WithTopic(topic).WithPayload(new byte[0]).WithQualityOfServiceLevel(qualityOfServiceLevel));
|
||||
|
||||
await Task.Delay(500);
|
||||
await c1.UnsubscribeAsync(topicFilter);
|
||||
|
||||
await Task.Delay(500);
|
||||
}
|
||||
finally
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Core.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class RoundtripTimeTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Round_Trip_Time()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var server = factory.CreateMqttServer();
|
||||
var receiverClient = factory.CreateMqttClient();
|
||||
var senderClient = factory.CreateMqttClient();
|
||||
|
||||
await server.StartAsync(new MqttServerOptionsBuilder().Build());
|
||||
|
||||
await receiverClient.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
|
||||
await receiverClient.SubscribeAsync("#");
|
||||
|
||||
await senderClient.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
|
||||
|
||||
TaskCompletionSource<string> response = null;
|
||||
|
||||
receiverClient.ApplicationMessageReceived += (sender, args) =>
|
||||
{
|
||||
response?.SetResult(args.ApplicationMessage.ConvertPayloadToString());
|
||||
};
|
||||
|
||||
var times = new List<TimeSpan>();
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
response = new TaskCompletionSource<string>();
|
||||
await senderClient.PublishAsync("test", DateTime.UtcNow.Ticks.ToString());
|
||||
response.Task.GetAwaiter().GetResult();
|
||||
|
||||
stopwatch.Stop();
|
||||
times.Add(stopwatch.Elapsed);
|
||||
stopwatch.Restart();
|
||||
}
|
||||
|
||||
await server.StopAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,19 +11,20 @@ namespace MQTTnet.Core.Tests
|
||||
/// publishes a message with a client and waits in the server until a message with the same topic is received
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static async Task PublishAndWaitForAsync(this IMqttClient client, IMqttServer server, MqttApplicationMessage message)
|
||||
public static async Task PublishAndWaitForAsync(this IMqttClient client, IMqttServer server, MqttApplicationMessage message)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
|
||||
EventHandler<MqttApplicationMessageReceivedEventArgs> handler = (sender, args) =>
|
||||
void Handler(object sender, MqttApplicationMessageReceivedEventArgs args)
|
||||
{
|
||||
if (args.ApplicationMessage.Topic == message.Topic)
|
||||
{
|
||||
tcs.SetResult(true);
|
||||
}
|
||||
};
|
||||
server.ApplicationMessageReceived += handler;
|
||||
|
||||
}
|
||||
|
||||
server.ApplicationMessageReceived += Handler;
|
||||
|
||||
try
|
||||
{
|
||||
await client.PublishAsync(message).ConfigureAwait(false);
|
||||
@@ -31,7 +32,7 @@ namespace MQTTnet.Core.Tests
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.ApplicationMessageReceived -= handler;
|
||||
server.ApplicationMessageReceived -= Handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user