Improve performance and drop support for old frameworks (#2068)

* Remove WebSocket4Net extension library

* Remove UWP support

* Drop support for all old frameworks

* Update CI

* Update CI

* Update CI

* Update CI

* Remove obsolete code

* Set default protocol version to 5.0.0

* Remove obsolete tests

* Remove old dependencies

* Reset release notes

* Move server to dedicated project

* Fix unit tests

* Update and cleanup nuget packages

* Fix unit tests
Refactor code

* No longer throw exception when receiving non success CONNACK

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable nuget signing

* Enable code signing

* Enable code signing

* Enable code signing

* Fix client endpoint handling

* Improve CI

* Fix CI

* Fix CI

* Fix CI

* Fix CI

* Import changes from version 4

* Cleanup target frameworks and remove obsolete code

* Drop support for dotnet7.0

* Remove managed client

* Version5 auditmode (#2016)

Added NuGet audit mode and some other settings to get informed about security issues.

* Address warnings from analyzers

* Support for ReadOnlySequence as payload (#2046)

* use ReadOnlySequence as payload

* fix build

* fix build

* skip sign in forks

* remove unnecessary owner

* tests and extensions

* remove test

* simplify WritePacketBuffer, remove unused helper

* Adjust namespaces

* Fix build errors

* Import latest fixes from main branch

* Adjust namespaces

---------

Co-authored-by: SeppPenner <HansM2013@gmx.de>
Co-authored-by: Martin Regen <mregen@microsoft.com>
This commit is contained in:
Christian
2024-08-24 11:47:21 +02:00
committed by GitHub
co-authored by SeppPenner Martin Regen
parent e18a91a4b5
commit 980a5d0a6d
459 changed files with 12197 additions and 16662 deletions
@@ -0,0 +1,50 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections;
using MQTTnet.Adapter;
using MQTTnet.AspNetCore;
using MQTTnet.Diagnostics.Logger;
using MQTTnet.Formatter;
using MQTTnet.Server;
namespace MQTTnet.Tests.ASP.Mockups;
public sealed class ConnectionHandlerMockup : IMqttServerAdapter
{
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
public TaskCompletionSource<MqttConnectionContext> Context { get; } = new();
public void Dispose()
{
}
public async Task OnConnectedAsync(ConnectionContext connection)
{
try
{
var formatter = new MqttPacketFormatterAdapter(new MqttBufferWriter(4096, 65535));
var context = new MqttConnectionContext(formatter, connection);
Context.TrySetResult(context);
await ClientHandler(context);
}
catch (Exception ex)
{
Context.TrySetException(ex);
}
}
public Task StartAsync(MqttServerOptions options, IMqttNetLogger logger)
{
return Task.CompletedTask;
}
public Task StopAsync()
{
return Task.CompletedTask;
}
}
@@ -0,0 +1,27 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.IO.Pipelines;
namespace MQTTnet.Tests.ASP.Mockups
{
public sealed class DuplexPipeMockup : IDuplexPipe
{
public DuplexPipeMockup()
{
var pool = new LimitedMemoryPool();
var pipeOptions = new PipeOptions(pool);
Receive = new Pipe(pipeOptions);
Send = new Pipe(pipeOptions);
}
PipeReader IDuplexPipe.Input => Receive.Reader;
PipeWriter IDuplexPipe.Output => Send.Writer;
public Pipe Receive { get; }
public Pipe Send { get; }
}
}
@@ -0,0 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Buffers;
namespace MQTTnet.Tests.ASP.Mockups
{
public sealed class LimitedMemoryPool : MemoryPool<byte>
{
protected override void Dispose(bool disposing)
{
}
public override IMemoryOwner<byte> Rent(int minBufferSize = -1)
{
return new MemoryOwner(minBufferSize);
}
public override int MaxBufferSize { get; }
}
}
@@ -0,0 +1,37 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
namespace MQTTnet.Tests.ASP.Mockups
{
public sealed class MemoryOwner : IMemoryOwner<byte>
{
readonly byte[] _raw;
public MemoryOwner(int size)
{
if (size <= 0)
{
size = 1024;
}
if (size > 4096)
{
size = 4096;
}
_raw = ArrayPool<byte>.Shared.Rent(size);
Memory = _raw;
}
public Memory<byte> Memory { get; }
public void Dispose()
{
ArrayPool<byte>.Shared.Return(_raw);
}
}
}
@@ -0,0 +1,130 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Connections;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.AspNetCore;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using MQTTnet.Tests.ASP.Mockups;
using MQTTnet.Tests.Helpers;
namespace MQTTnet.Tests.ASP
{
[TestClass]
public class MqttConnectionContextTest
{
[TestMethod]
public async Task TestCorruptedConnectPacket()
{
var writer = new MqttBufferWriter(4096, 65535);
var serializer = new MqttPacketFormatterAdapter(writer);
var pipe = new DuplexPipeMockup();
var connection = new DefaultConnectionContext();
connection.Transport = pipe;
var ctx = new MqttConnectionContext(serializer, connection);
await pipe.Receive.Writer.WriteAsync(writer.AddMqttHeader(MqttControlPacketType.Connect, Array.Empty<byte>()));
await Assert.ThrowsExceptionAsync<MqttProtocolViolationException>(() => ctx.ReceivePacketAsync(CancellationToken.None));
// the first exception should complete the pipes so if someone tries to use the connection after that it should throw immidiatly
await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => ctx.ReceivePacketAsync(CancellationToken.None));
}
// TODO: Fix test
// [TestMethod]
// public async Task TestEndpoint()
// {
// var mockup = new ConnectionHandlerMockup();
//
// using (var host = new WebHostBuilder().UseKestrel(kestrel => kestrel.ListenLocalhost(1883, listener => listener.Use((ctx, next) => mockup.OnConnectedAsync(ctx))))
// .UseStartup<Startup>()
// .ConfigureServices(
// (hostContext, services) =>
// {
// services.AddHostedMqttServer(o => o.WithoutDefaultEndpoint());
// services.AddSingleton<IMqttServerAdapter>(mockup);
// })
// .Build())
//
// using (var client = new MqttFactory().CreateMqttClient())
// {
// host.Start();
// await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build(), CancellationToken.None);
//
// var ctx = await mockup.Context.Task;
//
// var ep = IPEndPoint.Parse(ctx.Endpoint);
// Assert.IsNotNull(ep);
//
// Assert.IsNotNull(ctx);
// }
// }
// COMMENTED OUT DUE TO DEAD LOCK? OR VERY VERY SLOW PERFORMANCE ON LOCAL DEV MACHINE. TEST WAS STILL RUNNING AFTER SEVERAL MINUTES!
//[TestMethod]
//public async Task TestParallelWrites()
//{
// var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311);
// var pipe = new DuplexPipeMockup();
// var connection = new DefaultConnectionContext();
// connection.Transport = pipe;
// var ctx = new MqttConnectionContext(serializer, connection);
// var tasks = Enumerable.Range(1, 100).Select(_ => Task.Run(async () =>
// {
// for (int i = 0; i < 100; i++)
// {
// await ctx.SendPacketAsync(new MqttPublishPacket(), TimeSpan.Zero, CancellationToken.None).ConfigureAwait(false);
// }
// }));
// await Task.WhenAll(tasks).ConfigureAwait(false);
//}
[TestMethod]
public async Task TestLargePacket()
{
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311, new MqttBufferWriter(4096, 65535));
var pipe = new DuplexPipeMockup();
var connection = new DefaultConnectionContext();
connection.Transport = pipe;
var ctx = new MqttConnectionContext(serializer, connection);
await ctx.SendPacketAsync(new MqttPublishPacket { PayloadSegment = new byte[20_000] }, CancellationToken.None).ConfigureAwait(false);
var readResult = await pipe.Send.Reader.ReadAsync();
Assert.IsTrue(readResult.Buffer.Length > 20000);
}
[TestMethod]
public async Task TestReceivePacketAsyncThrowsWhenReaderCompleted()
{
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311, new MqttBufferWriter(4096, 65535));
var pipe = new DuplexPipeMockup();
var connection = new DefaultConnectionContext();
connection.Transport = pipe;
var ctx = new MqttConnectionContext(serializer, connection);
pipe.Receive.Writer.Complete();
await Assert.ThrowsExceptionAsync<MqttCommunicationException>(() => ctx.ReceivePacketAsync(CancellationToken.None));
}
class Startup
{
public void Configure(IApplicationBuilder app)
{
}
}
}
}
@@ -0,0 +1,46 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Buffers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.AspNetCore;
using MQTTnet.Formatter;
using MQTTnet.Packets;
namespace MQTTnet.Tests.ASP;
[TestClass]
public sealed class ReaderExtensionsTest
{
[TestMethod]
public void TestTryDeserialize()
{
var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311, new MqttBufferWriter(4096, 65535));
var buffer = serializer.Encode(new MqttPublishPacket { Topic = "a", PayloadSegment = new byte[5] }).Join();
var sequence = new ReadOnlySequence<byte>(buffer.Array, buffer.Offset, buffer.Count);
var part = sequence;
var consumed = part.Start;
var observed = part.Start;
var read = 0;
part = sequence.Slice(sequence.Start, 0); // empty message should fail
var result = serializer.TryDecode(part, out _, out consumed, out observed, out read);
Assert.IsFalse(result);
part = sequence.Slice(sequence.Start, 1); // partial fixed header should fail
result = serializer.TryDecode(part, out _, out consumed, out observed, out read);
Assert.IsFalse(result);
part = sequence.Slice(sequence.Start, 4); // partial body should fail
result = serializer.TryDecode(part, out _, out consumed, out observed, out read);
Assert.IsFalse(result);
part = sequence; // complete msg should work
result = serializer.TryDecode(part, out _, out consumed, out observed, out read);
Assert.IsTrue(result);
}
}
@@ -8,7 +8,6 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.LowLevelClient;
using MQTTnet.Packets;
@@ -27,7 +26,7 @@ namespace MQTTnet.Tests.Clients.LowLevelMqttClient
{
await testEnvironment.StartServer();
var factory = new MqttFactory();
var factory = new MqttClientFactory();
var lowLevelClient = factory.CreateLowLevelMqttClient();
await lowLevelClient.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build(), CancellationToken.None);
@@ -48,7 +47,7 @@ namespace MQTTnet.Tests.Clients.LowLevelMqttClient
{
await testEnvironment.StartServer();
var lowLevelClient = testEnvironment.Factory.CreateLowLevelMqttClient();
var lowLevelClient = testEnvironment.ClientFactory.CreateLowLevelMqttClient();
await lowLevelClient.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build(), CancellationToken.None);
@@ -60,7 +59,7 @@ namespace MQTTnet.Tests.Clients.LowLevelMqttClient
[ExpectedException(typeof(MqttCommunicationException))]
public async Task Connect_To_Not_Existing_Broker()
{
var client = new MqttFactory().CreateLowLevelMqttClient();
var client = new MqttClientFactory().CreateLowLevelMqttClient();
var options = new MqttClientOptionsBuilder().WithTcpServer("localhost").Build();
await client.ConnectAsync(options, CancellationToken.None).ConfigureAwait(false);
@@ -70,7 +69,7 @@ namespace MQTTnet.Tests.Clients.LowLevelMqttClient
[ExpectedException(typeof(MqttCommunicationException))]
public async Task Connect_To_Wrong_Host()
{
var client = new MqttFactory().CreateLowLevelMqttClient();
var client = new MqttClientFactory().CreateLowLevelMqttClient();
var options = new MqttClientOptionsBuilder().WithTcpServer("123.456.789.10").Build();
await client.ConnectAsync(options, CancellationToken.None).ConfigureAwait(false);
@@ -166,7 +165,7 @@ namespace MQTTnet.Tests.Clients.LowLevelMqttClient
{
await testEnvironment.StartServer();
var factory = new MqttFactory();
var factory = new MqttClientFactory();
var lowLevelClient = factory.CreateLowLevelMqttClient();
await lowLevelClient.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build(), CancellationToken.None);
@@ -1,818 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Diagnostics;
using MQTTnet.Extensions.ManagedClient;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using MQTTnet.Server;
using MQTTnet.Tests.Mockups;
namespace MQTTnet.Tests.Clients.ManagedMqttClient
{
[TestClass]
public sealed class ManagedMqttClient_Tests : BaseTestClass
{
[TestMethod]
public async Task Connect_To_Invalid_Server()
{
using (var testEnvironment = CreateTestEnvironment())
{
testEnvironment.IgnoreClientLogErrors = true;
var mqttClient = testEnvironment.CreateClient();
var managedClient = testEnvironment.Factory.CreateManagedMqttClient(mqttClient);
ConnectingFailedEventArgs connectingFailedEventArgs = null;
managedClient.ConnectingFailedAsync += args =>
{
connectingFailedEventArgs = args;
return CompletedTask.Instance;
};
await managedClient.StartAsync(
new ManagedMqttClientOptions
{
ClientOptions = testEnvironment.Factory.CreateClientOptionsBuilder().WithTimeout(TimeSpan.FromSeconds(2)).WithTcpServer("wrong_server", 1234).Build()
});
await managedClient.EnqueueAsync("test_topic_2");
SpinWait.SpinUntil(() => connectingFailedEventArgs != null, 10000);
// The wrong server must be reported in general.
Assert.IsNotNull(connectingFailedEventArgs);
Assert.IsNotNull(connectingFailedEventArgs.Exception);
Assert.IsNull(connectingFailedEventArgs.ConnectResult);
}
}
[TestMethod]
public async Task Drop_New_Messages_On_Full_Queue()
{
var factory = new MqttFactory();
var managedClient = factory.CreateManagedMqttClient();
try
{
var clientOptions = new ManagedMqttClientOptionsBuilder().WithMaxPendingMessages(5)
.WithPendingMessagesOverflowStrategy(MqttPendingMessagesOverflowStrategy.DropNewMessage);
clientOptions.WithClientOptions(o => o.WithTcpServer("localhost"));
await managedClient.StartAsync(clientOptions.Build());
await managedClient.EnqueueAsync("1");
await managedClient.EnqueueAsync("2");
await managedClient.EnqueueAsync("3");
await managedClient.EnqueueAsync("4");
await managedClient.EnqueueAsync("5");
await managedClient.EnqueueAsync("6");
await managedClient.EnqueueAsync("7");
await managedClient.EnqueueAsync("8");
Assert.AreEqual(5, managedClient.PendingApplicationMessagesCount);
}
finally
{
await managedClient.StopAsync();
}
}
[TestMethod]
public async Task Expose_Custom_Connection_Error()
{
using (var testEnvironment = CreateTestEnvironment())
{
var server = await testEnvironment.StartServer();
server.ValidatingConnectionAsync += args =>
{
args.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
return CompletedTask.Instance;
};
var managedClient = testEnvironment.Factory.CreateManagedMqttClient();
MqttClientDisconnectedEventArgs disconnectedArgs = null;
managedClient.DisconnectedAsync += args =>
{
disconnectedArgs = args;
return CompletedTask.Instance;
};
var clientOptions = testEnvironment.Factory.CreateManagedMqttClientOptionsBuilder().WithClientOptions(testEnvironment.CreateDefaultClientOptions()).Build();
await managedClient.StartAsync(clientOptions);
await LongTestDelay();
Assert.IsNotNull(disconnectedArgs);
Assert.AreEqual(MqttClientConnectResultCode.BadUserNameOrPassword, disconnectedArgs.ConnectResult.ResultCode);
}
}
[TestMethod]
public async Task ManagedClients_Will_Message_Send()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var receivedMessagesCount = 0;
var clientOptions = new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.WithWillTopic("My/last/will")
.WithWillQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
.Build();
var dyingClient = testEnvironment.CreateClient();
var dyingManagedClient = new MQTTnet.Extensions.ManagedClient.ManagedMqttClient(dyingClient, testEnvironment.ClientLogger);
await dyingManagedClient.StartAsync(new ManagedMqttClientOptionsBuilder().WithClientOptions(clientOptions).Build());
// Wait until the managed client is fully set up and running.
await Task.Delay(1000);
var receivingClient = await testEnvironment.ConnectClient();
receivingClient.ApplicationMessageReceivedAsync += e =>
{
Interlocked.Increment(ref receivedMessagesCount);
return CompletedTask.Instance;
};
await receivingClient.SubscribeAsync("My/last/will");
// Disposing the client will not sent a DISCONNECT packet so that connection is terminated
// which will lead to the will publish.
dyingManagedClient.Dispose();
// Wait for arrival of the will message at the receiver.
await Task.Delay(5000);
Assert.AreEqual(1, receivedMessagesCount);
}
}
[TestMethod]
public async Task Receive_While_Not_Cleanly_Disconnected()
{
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
{
await testEnvironment.StartServer(o => o.WithPersistentSessions());
var senderClient = await testEnvironment.ConnectClient();
// Prepare managed client.
var managedClient = testEnvironment.Factory.CreateManagedMqttClient();
await managedClient.SubscribeAsync("#");
var receivedMessages = testEnvironment.CreateApplicationMessageHandler(managedClient);
var managedClientOptions = new ManagedMqttClientOptions
{
ClientOptions = testEnvironment.Factory.CreateClientOptionsBuilder()
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.WithClientId(nameof(Receive_While_Not_Cleanly_Disconnected) + "_managed")
.WithCleanSession(false)
.Build()
};
await managedClient.StartAsync(managedClientOptions);
await LongTestDelay();
await LongTestDelay();
// Send test data.
await senderClient.PublishStringAsync("topic1");
await LongTestDelay();
await LongTestDelay();
receivedMessages.AssertReceivedCountEquals(1);
// Stop the managed client but keep session at server (not clean disconnect required).
await managedClient.StopAsync(false);
await LongTestDelay();
// Send new messages in the meantime.
await senderClient.PublishStringAsync("topic2", qualityOfServiceLevel: MqttQualityOfServiceLevel.ExactlyOnce);
await LongTestDelay();
// Start the managed client, it should receive the new message.
await managedClient.StartAsync(managedClientOptions);
await LongTestDelay();
receivedMessages.AssertReceivedCountEquals(2);
// Stop and start again, no new message should be received.
for (var i = 0; i < 3; i++)
{
await managedClient.StopAsync(false);
await LongTestDelay();
await managedClient.StartAsync(managedClientOptions);
await LongTestDelay();
}
receivedMessages.AssertReceivedCountEquals(2);
}
}
[TestMethod]
public async Task Start_Stop()
{
using (var testEnvironment = CreateTestEnvironment())
{
var server = await testEnvironment.StartServer();
var managedClient = new MQTTnet.Extensions.ManagedClient.ManagedMqttClient(testEnvironment.CreateClient(), new MqttNetEventLogger());
var clientOptions = new MqttClientOptionsBuilder().WithTcpServer("localhost", testEnvironment.ServerPort);
var connected = GetConnectedTask(managedClient);
await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder().WithClientOptions(clientOptions).Build());
await connected;
await managedClient.StopAsync();
await Task.Delay(500);
Assert.AreEqual(0, (await server.GetClientsAsync()).Count);
}
}
[TestMethod]
public async Task Storage_Queue_Drains()
{
using (var testEnvironment = CreateTestEnvironment())
{
testEnvironment.IgnoreClientLogErrors = true;
testEnvironment.IgnoreServerLogErrors = true;
await testEnvironment.StartServer();
var managedClient = new MQTTnet.Extensions.ManagedClient.ManagedMqttClient(testEnvironment.CreateClient(), new MqttNetEventLogger());
var clientOptions = new MqttClientOptionsBuilder().WithTcpServer("localhost", testEnvironment.ServerPort);
var storage = new ManagedMqttClientTestStorage();
var connected = GetConnectedTask(managedClient);
await managedClient.StartAsync(
new ManagedMqttClientOptionsBuilder().WithClientOptions(clientOptions).WithStorage(storage).WithAutoReconnectDelay(TimeSpan.FromSeconds(5)).Build());
await connected;
await testEnvironment.Server.StopAsync();
await managedClient.EnqueueAsync("1");
//Message should have been added to the storage queue in PublishAsync,
//and we are awaiting PublishAsync, so the message should already be
//in storage at this point (i.e. no waiting).
Assert.AreEqual(1, storage.GetMessageCount());
connected = GetConnectedTask(managedClient);
await testEnvironment.Server.StartAsync();
await connected;
//Wait 500ms here so the client has time to publish the queued message
await Task.Delay(500);
Assert.AreEqual(0, storage.GetMessageCount());
await managedClient.StopAsync();
}
}
[TestMethod]
public async Task Subscriptions_And_Unsubscriptions_Are_Made_And_Reestablished_At_Reconnect()
{
using (var testEnvironment = CreateTestEnvironment())
{
var unmanagedClient = testEnvironment.CreateClient();
var managedClient = await CreateManagedClientAsync(testEnvironment, unmanagedClient);
var received = SetupReceivingOfMessages(managedClient, 2);
// Perform some opposing subscriptions and unsubscriptions to verify
// that these conflicting subscriptions are handled correctly
await managedClient.SubscribeAsync("keptSubscribed");
await managedClient.SubscribeAsync("subscribedThenUnsubscribed");
await managedClient.UnsubscribeAsync("subscribedThenUnsubscribed");
await managedClient.UnsubscribeAsync("unsubscribedThenSubscribed");
await managedClient.SubscribeAsync("unsubscribedThenSubscribed");
//wait a bit for the subscriptions to become established before the messages are published
await Task.Delay(500);
var sendingClient = await testEnvironment.ConnectClient();
async Task PublishMessages()
{
await sendingClient.PublishBinaryAsync("keptSubscribed", new byte[] { 1 });
await sendingClient.PublishBinaryAsync("subscribedThenUnsubscribed", new byte[] { 1 });
await sendingClient.PublishBinaryAsync("unsubscribedThenSubscribed", new byte[] { 1 });
}
await PublishMessages();
async Task AssertMessagesReceived()
{
var messages = await received;
Assert.AreEqual("keptSubscribed", messages[0].Topic);
Assert.AreEqual("unsubscribedThenSubscribed", messages[1].Topic);
}
await AssertMessagesReceived();
var connected = GetConnectedTask(managedClient);
await unmanagedClient.DisconnectAsync();
// the managed client has to reconnect by itself
await connected;
// wait a bit so that the managed client can reestablish the subscriptions
await Task.Delay(500);
received = SetupReceivingOfMessages(managedClient, 2);
await PublishMessages();
// and then the same subscriptions need to exist again
await AssertMessagesReceived();
}
}
[TestMethod]
public async Task Subscriptions_Are_Cleared_At_Logout()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer().ConfigureAwait(false);
var sendingClient = await testEnvironment.ConnectClient().ConfigureAwait(false);
await sendingClient.PublishStringAsync("topic", "A", retain: true);
// Wait a bit for the retained message to be available
await LongTestDelay();
await sendingClient.DisconnectAsync();
// Now use the managed client and check if subscriptions get cleared properly.
var clientOptions = new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort);
var receivedManagedMessages = new List<MqttApplicationMessage>();
var managedClient = testEnvironment.Factory.CreateManagedMqttClient(testEnvironment.CreateClient());
managedClient.ApplicationMessageReceivedAsync += e =>
{
receivedManagedMessages.Add(e.ApplicationMessage);
return CompletedTask.Instance;
};
await managedClient.SubscribeAsync("topic");
await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder().WithClientOptions(clientOptions).WithAutoReconnectDelay(TimeSpan.FromSeconds(0.5)).Build());
await LongTestDelay();
Assert.AreEqual(1, receivedManagedMessages.Count);
await managedClient.StopAsync();
await LongTestDelay();
await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder().WithClientOptions(clientOptions).WithAutoReconnectDelay(TimeSpan.FromSeconds(0.5)).Build());
await LongTestDelay();
// After reconnect and then some delay, the retained message must not be received,
// showing that the subscriptions were cleared
Assert.AreEqual(1, receivedManagedMessages.Count);
// Make sure that it gets received after subscribing again.
await managedClient.SubscribeAsync("topic");
await LongTestDelay();
Assert.AreEqual(2, receivedManagedMessages.Count);
}
}
// This case also serves as a regression test for the previous behavior
// that subscriptions were only published at the ConnectionCheckInterval
[TestMethod]
public async Task Subscriptions_Are_Published_Immediately()
{
using (var testEnvironment = CreateTestEnvironment())
{
// Use a long connection check interval to verify that the subscriptions
// do not depend on the connection check interval anymore
var connectionCheckInterval = TimeSpan.FromSeconds(10);
var receivingClient = await CreateManagedClientAsync(testEnvironment, null, connectionCheckInterval);
var sendingClient = await testEnvironment.ConnectClient();
await sendingClient.PublishAsync(new MqttApplicationMessage { Topic = "topic", PayloadSegment = new ArraySegment<byte>(new byte[] { 1 }), Retain = true });
var subscribeTime = DateTime.UtcNow;
var messagesTask = SetupReceivingOfMessages(receivingClient, 1);
await receivingClient.SubscribeAsync("topic");
var messages = await messagesTask;
var elapsed = DateTime.UtcNow - subscribeTime;
Assert.IsTrue(elapsed < TimeSpan.FromSeconds(1), $"Subscriptions must be activated immediately, this one took {elapsed}");
Assert.AreEqual(messages.Single().Topic, "topic");
}
}
[TestMethod]
public async Task ManagedClients_CanInterceptPublishedMessage_PreventingPublish()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var receivedMessagesCount = 0;
var interceptedMessagesCount = 0;
var clientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.Build();
var sendingClient = testEnvironment.CreateClient();
var sendingManagedClient = new MQTTnet.Extensions.ManagedClient.ManagedMqttClient(sendingClient, testEnvironment.ClientLogger);
await sendingManagedClient.StartAsync(new ManagedMqttClientOptionsBuilder().WithClientOptions(clientOptions).Build());
// Wait until the managed client is fully set up and running.
await Task.Delay(1000);
var receivingClient = await testEnvironment.ConnectClient();
receivingClient.ApplicationMessageReceivedAsync += e =>
{
Interlocked.Increment(ref receivedMessagesCount);
return CompletedTask.Instance;
};
sendingManagedClient.InterceptPublishMessageAsync += e =>
{
Interlocked.Increment(ref interceptedMessagesCount);
e.AcceptPublish = false;
return CompletedTask.Instance;
};
await receivingClient.SubscribeAsync("My/last/will");
// Wait for arrival of the will message at the receiver.
await Task.Delay(5000);
await sendingManagedClient.EnqueueAsync("My/last/will", "hello world");
// Wait for arrival of the will message at the receiver.
await Task.Delay(5000);
Assert.AreEqual(0, receivedMessagesCount);
Assert.AreEqual(1, interceptedMessagesCount);
}
}
[TestMethod]
public async Task ManagedClients_CanInterceptPublishedMessage_AllowingPublish()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var receivedMessagesCount = 0;
var interceptedMessagesCount = 0;
var clientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.Build();
var sendingClient = testEnvironment.CreateClient();
var sendingManagedClient = new MQTTnet.Extensions.ManagedClient.ManagedMqttClient(sendingClient, testEnvironment.ClientLogger);
await sendingManagedClient.StartAsync(new ManagedMqttClientOptionsBuilder().WithClientOptions(clientOptions).Build());
// Wait until the managed client is fully set up and running.
await Task.Delay(1000);
var receivingClient = await testEnvironment.ConnectClient();
receivingClient.ApplicationMessageReceivedAsync += e =>
{
Interlocked.Increment(ref receivedMessagesCount);
return CompletedTask.Instance;
};
sendingManagedClient.InterceptPublishMessageAsync += e =>
{
Interlocked.Increment(ref interceptedMessagesCount);
e.AcceptPublish = true;
return CompletedTask.Instance;
};
await receivingClient.SubscribeAsync("My/last/will");
// Wait for arrival of the will message at the receiver.
await Task.Delay(5000);
await sendingManagedClient.EnqueueAsync("My/last/will", "hello world");
// Wait for arrival of the will message at the receiver.
await Task.Delay(5000);
Assert.AreEqual(1, receivedMessagesCount);
Assert.AreEqual(1, interceptedMessagesCount);
}
}
// This case also serves as a regression test for the previous behavior which re-published
// each and every existing subscriptions with every new subscription that was made
// (causing performance problems and having the visible symptom of retained messages being received again)
[TestMethod]
public async Task Subscriptions_Subscribe_Only_New_Subscriptions()
{
using (var testEnvironment = CreateTestEnvironment())
{
var managedClient = await CreateManagedClientAsync(testEnvironment);
var sendingClient = await testEnvironment.ConnectClient();
await managedClient.SubscribeAsync("topic");
//wait a bit for the subscription to become established
await Task.Delay(500);
await sendingClient.PublishAsync(new MqttApplicationMessage { Topic = "topic", PayloadSegment = new ArraySegment<byte>(new byte[] { 1 }), Retain = true });
var messages = await SetupReceivingOfMessages(managedClient, 1);
Assert.AreEqual(1, messages.Count);
Assert.AreEqual("topic", messages.Single().Topic);
await managedClient.SubscribeAsync("anotherTopic");
await Task.Delay(500);
// The subscription of the other topic must not trigger a re-subscription of the existing topic
// (and thus renewed receiving of the retained message)
Assert.AreEqual(1, messages.Count);
}
}
[TestMethod]
public async Task Subscribe_Does_Not_Hang_On_Server_Stop()
{
var timeout = TimeSpan.FromSeconds(2);
var testTimeout = TimeSpan.FromSeconds(timeout.TotalSeconds * 2);
const string topic = "test_topic_2";
using (var testEnvironment = CreateTestEnvironment())
using (var managedClient = await CreateManagedClientAsync(testEnvironment, timeout: timeout))
{
testEnvironment.IgnoreClientLogErrors = true;
bool reject = true;
var receivedOnServer = new SemaphoreSlim(0, 1);
var failedOnClient = new SemaphoreSlim(0, 1);
testEnvironment.Server.InterceptingInboundPacketAsync += e =>
{
if (e.Packet is MqttSubscribePacket)
{
if (reject)
{
e.ProcessPacket = false;
}
receivedOnServer.Release();
}
return CompletedTask.Instance;
};
managedClient.SynchronizingSubscriptionsFailedAsync += e =>
{
failedOnClient.Release();
return CompletedTask.Instance;
};
await managedClient.SubscribeAsync(topic);
Assert.IsTrue(await receivedOnServer.WaitAsync(testTimeout));
Assert.IsTrue(await failedOnClient.WaitAsync(testTimeout));
reject = false;
await managedClient.SubscribeAsync(topic);
Assert.IsTrue(await receivedOnServer.WaitAsync(testTimeout));
}
}
[TestMethod]
public async Task Unsubscribe_Does_Not_Hang_On_Server_Stop()
{
var timeout = TimeSpan.FromSeconds(2);
var testTimeout = TimeSpan.FromSeconds(timeout.TotalSeconds * 2);
const string topic = "test_topic_2";
using (var testEnvironment = CreateTestEnvironment())
using (var managedClient = await CreateManagedClientAsync(testEnvironment, timeout: timeout))
{
testEnvironment.IgnoreClientLogErrors = true;
bool reject = true;
var receivedOnServer = new SemaphoreSlim(0, 1);
var failedOnClient = new SemaphoreSlim(0, 1);
testEnvironment.Server.InterceptingInboundPacketAsync += e =>
{
if (e.Packet is MqttUnsubscribePacket)
{
if (reject)
{
e.ProcessPacket = false;
}
receivedOnServer.Release();
}
else if (e.Packet is MqttSubscribePacket)
{
receivedOnServer.Release();
}
return CompletedTask.Instance;
};
managedClient.SynchronizingSubscriptionsFailedAsync += e =>
{
failedOnClient.Release();
return CompletedTask.Instance;
};
await managedClient.SubscribeAsync(topic);
Assert.IsTrue(await receivedOnServer.WaitAsync(testTimeout));
await managedClient.UnsubscribeAsync(topic);
Assert.IsTrue(await receivedOnServer.WaitAsync(testTimeout));
Assert.IsTrue(await failedOnClient.WaitAsync(testTimeout));
reject = false;
await managedClient.UnsubscribeAsync(topic);
Assert.IsTrue(await receivedOnServer.WaitAsync(testTimeout));
}
}
[TestMethod]
public async Task Publish_Does_Not_Hang_On_Server_Error()
{
var timeout = TimeSpan.FromSeconds(2);
var testTimeout = TimeSpan.FromSeconds(timeout.TotalSeconds * 2);
const string topic = "test_topic_42";
using (var testEnvironment = CreateTestEnvironment())
using (var managedClient = await CreateManagedClientAsync(testEnvironment, timeout: timeout))
{
testEnvironment.IgnoreClientLogErrors = true;
bool reject = true;
var receivedOnServer = new TaskCompletionSource<object>();
managedClient.ApplicationMessageProcessedAsync += e => Task.FromResult(reject &= e.Exception is null);
testEnvironment.Server.InterceptingInboundPacketAsync += e =>
{
if (e.Packet is MqttPublishPacket)
{
if (reject)
{
e.ProcessPacket = false;
}
else
{
receivedOnServer.TrySetResult(null);
}
}
return CompletedTask.Instance;
};
await managedClient.EnqueueAsync(new MqttApplicationMessage { Topic = topic, PayloadSegment = new ArraySegment<byte>(new byte[] { 1 }), Retain = true, QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
var timeoutTask = Task.Delay(testTimeout);
var firstDone = await Task.WhenAny(receivedOnServer.Task, timeoutTask);
Assert.AreEqual(receivedOnServer.Task, firstDone, "Client is hung on publish!");
}
}
async Task<MQTTnet.Extensions.ManagedClient.ManagedMqttClient> CreateManagedClientAsync(
TestEnvironment testEnvironment,
IMqttClient underlyingClient = null,
TimeSpan? connectionCheckInterval = null,
string host = "localhost",
TimeSpan? timeout = null)
{
await testEnvironment.StartServer();
var clientOptions = new MqttClientOptionsBuilder().WithTcpServer(host, testEnvironment.ServerPort);
if (timeout != null)
{
clientOptions.WithTimeout(timeout.Value);
}
var managedOptions = new ManagedMqttClientOptionsBuilder().WithClientOptions(clientOptions).Build();
// Use a short connection check interval so that subscription operations are performed quickly
// in order to verify against a previous implementation that performed subscriptions only
// at connection check intervals
managedOptions.ConnectionCheckInterval = connectionCheckInterval ?? TimeSpan.FromSeconds(0.1);
var managedClient = new MQTTnet.Extensions.ManagedClient.ManagedMqttClient(underlyingClient ?? testEnvironment.CreateClient(), new MqttNetEventLogger());
var connected = GetConnectedTask(managedClient);
await managedClient.StartAsync(managedOptions);
await connected;
return managedClient;
}
/// <summary>
/// Returns a task that will finish when the
/// <paramref
/// name="managedClient" />
/// has connected
/// </summary>
Task GetConnectedTask(MQTTnet.Extensions.ManagedClient.ManagedMqttClient managedClient)
{
var connected = new TaskCompletionSource<bool>();
managedClient.ConnectedAsync += e =>
{
connected.TrySetResult(true);
return CompletedTask.Instance;
};
return connected.Task;
}
/// <summary>
/// Returns a task that will return the messages received on
/// <paramref
/// name="managedClient" />
/// when
/// <paramref
/// name="expectedNumberOfMessages" />
/// have been received
/// </summary>
Task<List<MqttApplicationMessage>> SetupReceivingOfMessages(MQTTnet.Extensions.ManagedClient.ManagedMqttClient managedClient, int expectedNumberOfMessages)
{
var receivedMessages = new List<MqttApplicationMessage>();
var result = new AsyncTaskCompletionSource<List<MqttApplicationMessage>>();
managedClient.ApplicationMessageReceivedAsync += e =>
{
receivedMessages.Add(e.ApplicationMessage);
if (receivedMessages.Count == expectedNumberOfMessages)
{
result.TrySetResult(receivedMessages);
}
return CompletedTask.Instance;
};
return result.Task;
}
}
public class ManagedMqttClientTestStorage : IManagedMqttClientStorage
{
IList<ManagedMqttApplicationMessage> _messages;
public int GetMessageCount()
{
return _messages.Count;
}
public Task<IList<ManagedMqttApplicationMessage>> LoadQueuedMessagesAsync()
{
if (_messages == null)
{
_messages = new List<ManagedMqttApplicationMessage>();
}
return Task.FromResult(_messages);
}
public Task SaveQueuedMessagesAsync(IList<ManagedMqttApplicationMessage> messages)
{
_messages = messages;
return CompletedTask.Instance;
}
}
}
@@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Internal;
@@ -24,7 +23,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
[ExpectedException(typeof(MqttCommunicationException))]
public async Task Connect_To_Invalid_Server_Port_Not_Opened()
{
var client = new MqttFactory().CreateMqttClient();
var client = new MqttClientFactory().CreateMqttClient();
using (var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
{
await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", 12345).Build(), timeout.Token);
@@ -35,7 +34,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
[ExpectedException(typeof(OperationCanceledException))]
public async Task Connect_To_Invalid_Server_Wrong_IP()
{
var client = new MqttFactory().CreateMqttClient();
var client = new MqttClientFactory().CreateMqttClient();
using (var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(2)))
{
await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("1.2.3.4").Build(), timeout.Token);
@@ -46,14 +45,14 @@ namespace MQTTnet.Tests.Clients.MqttClient
[ExpectedException(typeof(MqttCommunicationException))]
public async Task Connect_To_Invalid_Server_Wrong_Protocol()
{
var client = new MqttFactory().CreateMqttClient();
var client = new MqttClientFactory().CreateMqttClient();
await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("http://127.0.0.1", 12345).WithTimeout(TimeSpan.FromSeconds(2)).Build());
}
[TestMethod]
public async Task ConnectTimeout_Throws_Exception()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
using (var client = factory.CreateMqttClient())
{
var disconnectHandlerCalled = false;
@@ -96,7 +95,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
var client = await testEnvironment.ConnectClient();
var disconnectOptions = testEnvironment.Factory.CreateClientDisconnectOptionsBuilder().WithReason(MqttClientDisconnectOptionsReason.MessageRateTooHigh).Build();
var disconnectOptions = testEnvironment.ClientFactory.CreateClientDisconnectOptionsBuilder().WithReason(MqttClientDisconnectOptionsReason.MessageRateTooHigh).Build();
// Perform a clean disconnect.
await client.DisconnectAsync(disconnectOptions);
@@ -124,7 +123,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
var client = await testEnvironment.ConnectClient();
var disconnectOptions = testEnvironment.Factory.CreateClientDisconnectOptionsBuilder().WithReason(MqttClientDisconnectOptionsReason.MessageRateTooHigh).Build();
var disconnectOptions = testEnvironment.ClientFactory.CreateClientDisconnectOptionsBuilder().WithReason(MqttClientDisconnectOptionsReason.MessageRateTooHigh).Build();
// Perform a clean disconnect.
await client.DisconnectAsync(disconnectOptions);
@@ -152,7 +151,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
var client = await testEnvironment.ConnectClient();
var disconnectOptions = testEnvironment.Factory.CreateClientDisconnectOptionsBuilder().WithUserProperty("test_name", "test_value").Build();
var disconnectOptions = testEnvironment.ClientFactory.CreateClientDisconnectOptionsBuilder().WithUserProperty("test_name", "test_value").Build();
// Perform a clean disconnect.
await client.DisconnectAsync(disconnectOptions);
@@ -220,7 +219,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
var client = testEnvironment.CreateClient();
var response = await client.ConnectAsync(testEnvironment.CreateDefaultClientOptionsBuilder().WithoutThrowOnNonSuccessfulConnectResponse().Build());
var response = await client.ConnectAsync(testEnvironment.CreateDefaultClientOptionsBuilder().Build());
Assert.IsNotNull(response);
Assert.AreEqual(MqttClientConnectResultCode.QuotaExceeded, response.ResultCode);
@@ -234,7 +233,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
{
try
{
var mqttFactory = new MqttFactory();
var mqttFactory = new MqttClientFactory();
using (var mqttClient = mqttFactory.CreateMqttClient())
{
await mqttClient.SubscribeAsync("test", MqttQualityOfServiceLevel.AtLeastOnce);
@@ -3,16 +3,15 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Internal;
@@ -107,7 +106,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
[TestMethod]
public async Task Disconnect_Event_Contains_Exception()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
using (var client = factory.CreateMqttClient())
{
Exception ex = null;
@@ -248,7 +247,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
[TestMethod]
public async Task Invalid_Connect_Throws_Exception()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
using (var client = factory.CreateMqttClient())
{
try
@@ -298,7 +297,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
Assert.IsNotNull(receivedMessage);
Assert.AreEqual("A", receivedMessage.Topic);
Assert.AreEqual(null, receivedMessage.PayloadSegment.Array);
Assert.AreEqual(0, receivedMessage.Payload.Length);
}
}
@@ -509,7 +508,7 @@ namespace MQTTnet.Tests.Clients.MqttClient
client2.ApplicationMessageReceivedAsync += e =>
{
client2TopicResults.Add(Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment.ToArray()));
client2TopicResults.Add(Encoding.UTF8.GetString(e.ApplicationMessage.Payload.ToArray()));
return CompletedTask.Instance;
};
@@ -926,54 +925,5 @@ namespace MQTTnet.Tests.Clients.MqttClient
Assert.IsFalse(disconnectedFired);
}
}
[TestMethod]
public void Backward_compatible_TCP_options()
{
var options = new MqttClientOptionsBuilder().WithTcpServer("host", 3).Build();
Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server);
Assert.AreEqual(3, ((MqttClientTcpOptions)options.ChannelOptions).Port);
options = new MqttClientOptions
{
ChannelOptions = new MqttClientTcpOptions
{
Server = "host",
Port = 3
}
};
Assert.AreEqual("host:3", options.ChannelOptions.ToString());
Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server);
Assert.AreEqual(3, ((MqttClientTcpOptions)options.ChannelOptions).Port);
options = new MqttClientOptionsBuilder().WithEndPoint(new DnsEndPoint("host", 3)).Build();
Assert.AreEqual("Unspecified/host:3", options.ChannelOptions.ToString());
Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server);
Assert.AreEqual(3, ((MqttClientTcpOptions)options.ChannelOptions).Port);
options = new MqttClientOptionsBuilder().WithTcpServer("host").Build();
Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server);
Assert.AreEqual(1883, ((MqttClientTcpOptions)options.ChannelOptions).Port);
Assert.AreEqual("Unspecified/host:1883", options.ChannelOptions.ToString());
options = new MqttClientOptionsBuilder().WithTlsOptions(o => o.UseTls()).WithTcpServer("host").Build();
Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server);
Assert.AreEqual(8883, ((MqttClientTcpOptions)options.ChannelOptions).Port);
options = new MqttClientOptions
{
ChannelOptions = new MqttClientTcpOptions
{
Server = "host"
}
};
Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server);
Assert.AreEqual(null, ((MqttClientTcpOptions)options.ChannelOptions).Port);
}
}
}
@@ -5,7 +5,6 @@
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
namespace MQTTnet.Tests.Clients
{
@@ -18,7 +17,7 @@ namespace MQTTnet.Tests.Clients
var options = new MqttClientOptionsBuilder()
.WithConnectionUri("mqtt://user:password@127.0.0.1")
.Build();
Assert.AreEqual("user", options.Credentials.GetUserName(null));
Assert.IsTrue(Encoding.UTF8.GetBytes("password").SequenceEqual(options.Credentials.GetPassword(null)));
}
@@ -4,7 +4,7 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Diagnostics;
using MQTTnet.Diagnostics.Logger;
namespace MQTTnet.Tests.Diagnostics
{
@@ -44,7 +44,7 @@ namespace MQTTnet.Tests.Diagnostics
Assert.AreEqual(4, logMessagesCount);
}
[TestMethod]
public void Use_Custom_Log_Id()
{
@@ -56,7 +56,7 @@ namespace MQTTnet.Tests.Diagnostics
Assert.AreEqual("logId", e.LogMessage.LogId);
Assert.AreEqual("Source1", e.LogMessage.Source);
};
childLogger.Verbose("Verbose");
childLogger.Info("Info");
childLogger.Warning((Exception)null, "Warning");
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Formatter;
using MQTTnet.Internal;
namespace MQTTnet.Tests.Diagnostics
@@ -20,24 +21,25 @@ namespace MQTTnet.Tests.Diagnostics
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
using (var mqttClient = testEnvironment.CreateClient())
{
var mqttClientOptions = testEnvironment.Factory.CreateClientOptionsBuilder()
var mqttClientOptions = testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithClientId("CLIENT_ID") // Must be fixed.
.WithProtocolVersion(MqttProtocolVersion.V311)
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.Build();
var packets = new List<string>();
mqttClient.InspectPacketAsync += eventArgs =>
{
packets.Add(eventArgs.Direction + ":" + Convert.ToBase64String(eventArgs.Buffer));
return CompletedTask.Instance;
};
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
Assert.AreEqual(2, packets.Count);
Assert.AreEqual("Outbound:ECwABE1RVFQEAgAPACBJbnNwZWN0X0NsaWVudF9QYWNrZXRzX0NMSUVOVF9JRA==", packets[0]); // CONNECT
Assert.AreEqual("Inbound:IAIAAA==", packets[1]); // CONNACK
@@ -3,7 +3,8 @@
// See the LICENSE file in the project root for more information.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Diagnostics;
using MQTTnet.Diagnostics.Logger;
namespace MQTTnet.Tests.Diagnostics
{
@@ -14,16 +15,16 @@ namespace MQTTnet.Tests.Diagnostics
public void Log_With_Source()
{
MqttNetLogMessage logMessage = null;
var logger = new MqttNetEventLogger();
logger.LogMessagePublished += (s, e) =>
{
logMessage = e.LogMessage;
};
var sourceLogger = logger.WithSource("The_Source");
sourceLogger.Info("MESSAGE", (object)null, (object)null);
Assert.AreEqual("The_Source", logMessage.Source);
}
}
@@ -61,21 +61,21 @@ namespace MQTTnet.Tests.Extensions
var template = new MqttTopicTemplate("A/B/{foo}/D");
template.WithParameter("foo", "a/b");
}
[TestMethod]
public void AcceptsEmptyValue()
{
var template = new MqttTopicTemplate("A/B/{foo}/D");
template.WithParameter("foo", "");
}
[TestMethod]
[ExpectedException(typeof(MqttProtocolViolationException))]
public void RejectsEmptyTemplate()
{
var _ = new MqttTopicTemplate("");
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void RejectsNullTemplate()
@@ -83,14 +83,13 @@ namespace MQTTnet.Tests.Extensions
var _ = new MqttTopicTemplate(null);
}
[TestMethod]
public void IgnoresEmptyParameters()
{
var template = new MqttTopicTemplate("A/B/{}/D");
Assert.IsFalse(template.Parameters.Any());
}
[TestMethod]
public void AcceptsValidTopics()
{
@@ -127,6 +126,7 @@ namespace MQTTnet.Tests.Extensions
.WithAtLeastOnceQoS()
.WithNoLocal()
.Build();
Assert.AreEqual("A/v1/+/F", filter.Topic);
}
@@ -134,11 +134,12 @@ namespace MQTTnet.Tests.Extensions
public void SubscriptionSupport2()
{
var template = new MqttTopicTemplate("A/v1/{param}/F");
var subscribeOptions = new MqttFactory().CreateSubscribeOptionsBuilder()
var subscribeOptions = new MqttClientFactory().CreateSubscribeOptionsBuilder()
.WithTopicTemplate(template)
.WithSubscriptionIdentifier(5)
.Build();
Assert.AreEqual("A/v1/+/F", subscribeOptions.TopicFilters[0].Topic);
}
@@ -170,7 +171,7 @@ namespace MQTTnet.Tests.Extensions
public void SendAndSubscribeSupport2()
{
var template = new MqttTopicTemplate("App/v1/{sender}/message");
Assert.ThrowsException<ArgumentException>(() =>
Assert.ThrowsException<ArgumentException>(() =>
template.BuildMessage());
}
@@ -184,7 +185,7 @@ namespace MQTTnet.Tests.Extensions
// possible improvement: Assert.AreEqual("A/v1/+/F", canonicalFilter.TopicFilter);
Assert.AreEqual("A/v1/+", canonicalFilter.TopicFilter);
Assert.AreEqual("A/v1/+/#", canonicalFilter.TopicTreeRootFilter);
var template2b = new MqttTopicTemplate("A/v1/E/X");
canonicalFilter = MqttTopicTemplate.FindCanonicalPrefix(new[] { template1, template2, template3, template2b });
Assert.AreEqual("A/v1/+", canonicalFilter.Template);
@@ -197,7 +198,7 @@ namespace MQTTnet.Tests.Extensions
Assert.AreEqual("A/+", canonicalFilter2.TopicFilter);
Assert.AreEqual("A/+/#", canonicalFilter2.TopicTreeRootFilter);
}
[TestMethod]
public void CanonicalPrefixFilterSimple1()
{
@@ -209,7 +210,7 @@ namespace MQTTnet.Tests.Extensions
Assert.AreEqual("#", template.TopicFilter);
Assert.AreEqual("#", template.Template);
}
[TestMethod]
public void CanonicalPrefixFilterSimple2()
{
@@ -220,7 +221,7 @@ namespace MQTTnet.Tests.Extensions
});
Assert.AreEqual("A/v1/+", template.TopicFilter);
}
[TestMethod]
public void CanonicalPrefixFilterSimple3()
{
@@ -232,7 +233,7 @@ namespace MQTTnet.Tests.Extensions
Assert.AreEqual("A/v1/+/+", template.TopicFilter);
Assert.AreEqual("A/v1/{param}/+", template.Template);
}
[TestMethod]
public void CanonicalPrefixFilterSimple4()
{
@@ -244,8 +245,7 @@ namespace MQTTnet.Tests.Extensions
Assert.AreEqual("A/v1/+/+", template.TopicFilter);
Assert.AreEqual("A/v1/{param}/+", template.Template);
}
[TestMethod]
public void CanonicalPrefixFilterSimple5()
{
@@ -257,7 +257,7 @@ namespace MQTTnet.Tests.Extensions
Assert.AreEqual("A/+", template.TopicFilter);
Assert.AreEqual("A/+/#", template.TopicTreeRootFilter);
}
[TestMethod]
public void CanonicalPrefixFilterSimple6()
{
+1 -2
View File
@@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Extensions.Rpc;
using MQTTnet.Formatter;
@@ -186,7 +185,7 @@ namespace MQTTnet.Tests.Extensions
[TestMethod]
public void Use_Factory()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
using (var client = factory.CreateMqttClient())
{
var rpcClient = factory.CreateMqttRpcClient(client);
@@ -1,51 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Extensions.WebSocket4Net;
using MQTTnet.Tests.Helpers;
namespace MQTTnet.Tests.Extensions
{
[TestClass]
public sealed class WebSocket4Net_Tests
{
[TestMethod]
[ExpectedException(typeof(MqttCommunicationException))]
public async Task Connect_Failed_With_Invalid_Server()
{
var factory = new MqttFactory().UseWebSocket4Net();
using (var client = factory.CreateMqttClient())
{
var options = new MqttClientOptionsBuilder().WithWebSocketServer(o => o.WithUri("ws://a.b/mqtt")).WithTimeout(TimeSpan.FromSeconds(2)).Build();
await client.ConnectAsync(options).ConfigureAwait(false);
}
}
[TestMethod]
public void Use_Correct_Adapter()
{
// Should not throw exception
var factory = new MqttFactory().UseWebSocket4Net();
using (var client = factory.CreateMqttClient())
{
var adapterFactory = client.GetFieldValue("_adapterFactory");
Assert.IsInstanceOfType(adapterFactory, typeof(WebSocket4NetMqttClientAdapterFactory));
}
}
[TestMethod]
public void Use_WebSocket4Net()
{
// Should not throw exception
new MqttFactory().UseWebSocket4Net();
}
}
}
@@ -2,13 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Diagnostics;
using MQTTnet.Extensions.ManagedClient;
using MQTTnet.Internal;
using MQTTnet.Server;
namespace MQTTnet.Tests.Factory
@@ -16,66 +10,11 @@ namespace MQTTnet.Tests.Factory
[TestClass]
public sealed class MqttFactory_Tests : BaseTestClass
{
[TestMethod]
public async Task Create_Managed_Client_With_Logger()
{
var factory = new MqttFactory();
// This test compares
// 1. correct logID
var logId = "logId";
var hasInvalidLogId = false;
// 2. if the total log calls are the same for global and local
//var globalLogCount = 0;
var localLogCount = 0;
var logger = new MqttNetEventLogger(logId);
logger.LogMessagePublished += (s, e) =>
{
if (e.LogMessage.LogId != logId)
{
hasInvalidLogId = true;
}
Interlocked.Increment(ref localLogCount);
};
var managedClient = factory.CreateManagedMqttClient(logger);
try
{
var clientOptions = new ManagedMqttClientOptionsBuilder();
clientOptions.WithClientOptions(o => o.WithTcpServer("this_is_an_invalid_host").WithTimeout(TimeSpan.FromSeconds(1)));
// try connect to get some log entries
await managedClient.StartAsync(clientOptions.Build());
// wait at least connect timeout or we have some log messages
var tcs = new TaskCompletionSource<object>();
managedClient.ConnectingFailedAsync += e =>
{
tcs.TrySetResult(null);
return CompletedTask.Instance;
};
await Task.WhenAny(Task.Delay(managedClient.Options.ClientOptions.Timeout), tcs.Task);
}
finally
{
await managedClient.StopAsync();
}
await Task.Delay(500);
Assert.IsFalse(hasInvalidLogId);
Assert.AreNotEqual(0, localLogCount);
}
[TestMethod]
public void Create_ApplicationMessageBuilder()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
var builder = factory.CreateApplicationMessageBuilder();
Assert.IsNotNull(builder);
@@ -84,7 +23,7 @@ namespace MQTTnet.Tests.Factory
[TestMethod]
public void Create_ClientOptionsBuilder()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
var builder = factory.CreateClientOptionsBuilder();
Assert.IsNotNull(builder);
@@ -93,7 +32,7 @@ namespace MQTTnet.Tests.Factory
[TestMethod]
public void Create_ServerOptionsBuilder()
{
var factory = new MqttFactory();
var factory = new MqttServerFactory();
var builder = factory.CreateServerOptionsBuilder();
Assert.IsNotNull(builder);
@@ -102,7 +41,7 @@ namespace MQTTnet.Tests.Factory
[TestMethod]
public void Create_SubscribeOptionsBuilder()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
var builder = factory.CreateSubscribeOptionsBuilder();
Assert.IsNotNull(builder);
@@ -111,7 +50,7 @@ namespace MQTTnet.Tests.Factory
[TestMethod]
public void Create_UnsubscribeOptionsBuilder()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
var builder = factory.CreateUnsubscribeOptionsBuilder();
Assert.IsNotNull(builder);
@@ -120,7 +59,7 @@ namespace MQTTnet.Tests.Factory
[TestMethod]
public void Create_TopicFilterBuilder()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
var builder = factory.CreateTopicFilterBuilder();
Assert.IsNotNull(builder);
@@ -129,7 +68,7 @@ namespace MQTTnet.Tests.Factory
[TestMethod]
public void Create_MqttServer()
{
var factory = new MqttFactory();
var factory = new MqttServerFactory();
var server = factory.CreateMqttServer(new MqttServerOptionsBuilder().Build());
Assert.IsNotNull(server);
@@ -138,7 +77,7 @@ namespace MQTTnet.Tests.Factory
[TestMethod]
public void Create_MqttClient()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
var client = factory.CreateMqttClient();
Assert.IsNotNull(client);
@@ -147,19 +86,10 @@ namespace MQTTnet.Tests.Factory
[TestMethod]
public void Create_LowLevelMqttClient()
{
var factory = new MqttFactory();
var factory = new MqttClientFactory();
var client = factory.CreateLowLevelMqttClient();
Assert.IsNotNull(client);
}
[TestMethod]
public void Create_ManagedMqttClient()
{
var factory = new MqttFactory();
var client = factory.CreateManagedMqttClient();
Assert.IsNotNull(client);
}
}
}
@@ -70,6 +70,7 @@ namespace MQTTnet.Tests.Formatter
Assert.AreEqual(5, remainingData.Length);
}
[TestMethod]
public void Read_Various_Positions_and_Offsets()
{
@@ -3,14 +3,14 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Diagnostics.Logger;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Packets;
@@ -213,7 +213,7 @@ namespace MQTTnet.Tests.Formatter
MqttSubscribeReasonCode.UnspecifiedError
}
};
DeserializeAndCompare(p, "kAYAewABAoA=");
}
@@ -328,7 +328,7 @@ namespace MQTTnet.Tests.Formatter
Assert.IsNotNull(publishPacketCopy);
Assert.AreEqual(publishPacket.Topic, publishPacketCopy.Topic);
CollectionAssert.AreEqual(publishPacket.PayloadSegment.ToArray(), publishPacketCopy.PayloadSegment.ToArray());
CollectionAssert.AreEqual(publishPacket.Payload.ToArray(), publishPacketCopy.Payload.ToArray());
// Now modify the payload and test again.
publishPacket.PayloadSegment = new ArraySegment<byte>(Encoding.UTF8.GetBytes("MQTT"));
@@ -338,7 +338,7 @@ namespace MQTTnet.Tests.Formatter
Assert.IsNotNull(publishPacketCopy2);
Assert.AreEqual(publishPacket.Topic, publishPacketCopy2.Topic);
CollectionAssert.AreEqual(publishPacket.PayloadSegment.ToArray(), publishPacketCopy2.PayloadSegment.ToArray());
CollectionAssert.AreEqual(publishPacket.Payload.ToArray(), publishPacketCopy2.Payload.ToArray());
}
[TestMethod]
@@ -506,7 +506,7 @@ namespace MQTTnet.Tests.Formatter
MqttSubscribeReasonCode.UnspecifiedError
}
};
SerializeAndCompare(p, "kAYAewABAoA=");
}
@@ -587,7 +587,7 @@ namespace MQTTnet.Tests.Formatter
return packetFormatterAdapter.ProtocolVersion;
}
TPacket Roundtrip<TPacket>(TPacket packet, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311, MqttBufferWriter bufferWriter = null) where TPacket : MqttPacket
TPacket Roundtrip<TPacket>(TPacket packet, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311, MqttBufferReader bufferReader = null, MqttBufferWriter bufferWriter = null) where TPacket : MqttPacket
{
var writer = bufferWriter ?? WriterFactory();
var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer);
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -322,7 +323,7 @@ namespace MQTTnet.Tests.Formatter
Assert.AreEqual(publishPacket.PacketIdentifier, deserialized.PacketIdentifier);
Assert.AreEqual(publishPacket.Dup, deserialized.Dup);
Assert.AreEqual(publishPacket.Retain, deserialized.Retain);
CollectionAssert.AreEqual(publishPacket.PayloadSegment.ToArray(), deserialized.PayloadSegment.ToArray());
CollectionAssert.AreEqual(publishPacket.Payload.ToArray(), deserialized.Payload.ToArray());
Assert.AreEqual(publishPacket.QualityOfServiceLevel, deserialized.QualityOfServiceLevel);
Assert.AreEqual(publishPacket.Topic, deserialized.Topic);
Assert.AreEqual(null, deserialized.ResponseTopic); // Not supported in v3.1.1.
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -283,7 +284,7 @@ namespace MQTTnet.Tests.Formatter
Assert.AreEqual(publishPacket.PacketIdentifier, deserialized.PacketIdentifier);
Assert.AreEqual(publishPacket.Dup, deserialized.Dup);
Assert.AreEqual(publishPacket.Retain, deserialized.Retain);
CollectionAssert.AreEqual(publishPacket.PayloadSegment.ToArray(), deserialized.PayloadSegment.ToArray());
CollectionAssert.AreEqual(publishPacket.Payload.ToArray(), deserialized.Payload.ToArray());
Assert.AreEqual(publishPacket.QualityOfServiceLevel, deserialized.QualityOfServiceLevel);
Assert.AreEqual(publishPacket.Topic, deserialized.Topic);
Assert.AreEqual(publishPacket.ResponseTopic, deserialized.ResponseTopic);
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using MQTTnet.Client;
using MQTTnet.Tests.Mockups;
namespace MQTTnet.Tests.Helpers
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
@@ -19,7 +20,7 @@ namespace MQTTnet.Tests.Internal
public async Task Connect_Send_Receive()
{
var crossPlatformSocket = new CrossPlatformSocket(ProtocolType.Tcp);
await crossPlatformSocket.ConnectAsync("www.google.de", 80, CancellationToken.None);
await crossPlatformSocket.ConnectAsync(new DnsEndPoint("www.google.de", 80), CancellationToken.None);
var requestBuffer = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\nHost: www.google.de\r\n\r\n");
await crossPlatformSocket.SendAsync(new ArraySegment<byte>(requestBuffer), System.Net.Sockets.SocketFlags.None);
@@ -42,7 +43,7 @@ namespace MQTTnet.Tests.Internal
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(5));
cancellationToken.Token.Register(() => crossPlatformSocket.Dispose());
await crossPlatformSocket.ConnectAsync("www.google.de", 54321, cancellationToken.Token);
await crossPlatformSocket.ConnectAsync(new DnsEndPoint("www.google.de", 54321), cancellationToken.Token);
}
//[TestMethod]
+13 -9
View File
@@ -1,28 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net7.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net48</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<LangVersion>7.3</LangVersion>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
<DisableImplicitAspNetCoreAnalyzers>true</DisableImplicitAspNetCoreAnalyzers>
<NoWarn>1591;NETSDK1138</NoWarn>
<NoWarn>1591;NETSDK1138;NU1803;NU1901;NU1902</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NuGetAuditMode>all</NuGetAuditMode>
<NuGetAudit>true</NuGetAudit>
<AnalysisLevel>latest-Recommended</AnalysisLevel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.3.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.3.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj" />
<ProjectReference Include="..\..\Source\MQTTnet.Server\MQTTnet.Server.csproj" />
<ProjectReference Include="..\..\Source\MQTTnet.Extensions.Rpc\MQTTnet.Extensions.Rpc.csproj" />
<ProjectReference Include="..\..\Source\MQTTnet\MQTTnet.csproj" />
<ProjectReference Include="..\MQTTnet.AspnetCore\MQTTnet.AspNetCore.csproj" />
<ProjectReference Include="..\MQTTnet.Extensions.TopicTemplate\MQTTnet.Extensions.TopicTemplate.csproj" />
<ProjectReference Include="..\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj" />
</ItemGroup>
</Project>
+105 -4
View File
@@ -2,11 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Packets;
@@ -61,7 +62,7 @@ namespace MQTTnet.Tests.MQTTv5
Assert.AreEqual(2, receivedMessage.UserProperties.Count);
}
}
[TestMethod]
public async Task Connect()
{
@@ -128,6 +129,54 @@ namespace MQTTnet.Tests.MQTTv5
}
}
[TestMethod]
public async Task Publish_QoS_0_LargeBuffer()
{
using var recyclableMemoryStream = GetLargePayload();
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var client = await testEnvironment.ConnectClient(o => o.WithProtocolVersion(MqttProtocolVersion.V500));
var result = await client.PublishSequenceAsync("a", recyclableMemoryStream.GetReadOnlySequence());
await client.DisconnectAsync();
Assert.AreEqual(MqttClientPublishReasonCode.Success, result.ReasonCode);
}
}
[TestMethod]
public async Task Publish_QoS_1_LargeBuffer()
{
using var recyclableMemoryStream = GetLargePayload();
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var client = await testEnvironment.ConnectClient(o => o.WithProtocolVersion(MqttProtocolVersion.V500));
var result = await client.PublishSequenceAsync("a", recyclableMemoryStream.GetReadOnlySequence(), MqttQualityOfServiceLevel.AtLeastOnce);
await client.DisconnectAsync();
Assert.AreEqual(MqttClientPublishReasonCode.NoMatchingSubscribers, result.ReasonCode);
}
}
[TestMethod]
public async Task Publish_QoS_2_LargeBuffer()
{
using var recyclableMemoryStream = GetLargePayload();
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var client = await testEnvironment.ConnectClient(o => o.WithProtocolVersion(MqttProtocolVersion.V500));
var result = await client.PublishSequenceAsync("a", recyclableMemoryStream.GetReadOnlySequence(), MqttQualityOfServiceLevel.ExactlyOnce);
await client.DisconnectAsync();
Assert.AreEqual(MqttClientPublishReasonCode.NoMatchingSubscribers, result.ReasonCode);
}
}
[TestMethod]
public async Task Publish_QoS_0()
{
@@ -173,6 +222,45 @@ namespace MQTTnet.Tests.MQTTv5
}
}
[TestMethod]
public async Task Publish_With_RecyclableMemoryStream()
{
var memoryManager = new RecyclableMemoryStreamManager(options: new RecyclableMemoryStreamManager.Options { BlockSize = 4096 });
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var client = await testEnvironment.ConnectClient(o => o.WithProtocolVersion(MqttProtocolVersion.V500));
const int payloadSize = 100000;
using var memoryStream = memoryManager.GetStream();
byte testValue = 0;
while (memoryStream.Length < payloadSize)
{
memoryStream.WriteByte(testValue++);
}
var applicationMessage = new MqttApplicationMessageBuilder()
.WithTopic("Hello")
.WithPayload(memoryStream.GetReadOnlySequence())
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)
.WithUserProperty("x", "1")
.WithUserProperty("y", "2")
.WithResponseTopic("response")
.WithContentType("text")
.WithMessageExpiryInterval(50)
.WithCorrelationData(new byte[12])
.WithTopicAlias(2)
.Build();
var result = await client.PublishAsync(applicationMessage);
await client.DisconnectAsync();
Assert.AreEqual(MqttClientPublishReasonCode.Success, result.ReasonCode);
}
}
[TestMethod]
public async Task Publish_With_Properties()
{
@@ -208,7 +296,7 @@ namespace MQTTnet.Tests.MQTTv5
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var client1 = await testEnvironment.ConnectClient(o => o.WithProtocolVersion(MqttProtocolVersion.V500).WithClientId("client1"));
var testMessageHandler = testEnvironment.CreateApplicationMessageHandler(client1);
@@ -273,9 +361,22 @@ namespace MQTTnet.Tests.MQTTv5
Assert.AreEqual(applicationMessage.ResponseTopic, receivedMessage.ResponseTopic);
Assert.AreEqual(applicationMessage.MessageExpiryInterval, receivedMessage.MessageExpiryInterval);
CollectionAssert.AreEqual(applicationMessage.CorrelationData, receivedMessage.CorrelationData);
CollectionAssert.AreEqual(applicationMessage.PayloadSegment.ToArray(), receivedMessage.PayloadSegment.ToArray());
CollectionAssert.AreEqual(applicationMessage.Payload.ToArray(), receivedMessage.Payload.ToArray());
CollectionAssert.AreEqual(applicationMessage.UserProperties, receivedMessage.UserProperties);
}
}
private RecyclableMemoryStream GetLargePayload()
{
var memoryManager = new RecyclableMemoryStreamManager();
var memoryStream = memoryManager.GetStream();
for (var i = 0; i < 100000; i++)
{
memoryStream.WriteByte((byte)i);
}
memoryStream.Position = 0;
return memoryStream;
}
}
}
+4 -5
View File
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Tests.Mockups;
using System.Threading;
@@ -23,18 +22,18 @@ namespace MQTTnet.Tests.MQTTv5
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var clientOptions = new MqttClientOptionsBuilder().WithWillTopic("My/last/will").WithWillQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce).WithProtocolVersion(MqttProtocolVersion.V500);
var c1 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500));
var receivedMessagesCount = 0;
c1.ApplicationMessageReceivedAsync += e =>
{
Interlocked.Increment(ref receivedMessagesCount);
return CompletedTask.Instance;
};
await c1.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("#").Build());
var c2 = await testEnvironment.ConnectClient(clientOptions);
@@ -220,7 +219,7 @@ namespace MQTTnet.Tests.MQTTv5
static MqttClientOptions CreateClientOptions(TestEnvironment testEnvironment, string clientId, bool cleanSession, uint sessionExpiryInterval)
{
return testEnvironment.Factory.CreateClientOptionsBuilder()
return testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithProtocolVersion(MqttProtocolVersion.V500)
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.WithSessionExpiryInterval(sessionExpiryInterval)
@@ -2,13 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using MQTTnet.Channel;
using MQTTnet.Internal;
using System.Buffers;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Channel;
using MQTTnet.Internal;
namespace MQTTnet.Tests.Mockups
{
@@ -47,9 +47,12 @@ namespace MQTTnet.Tests.Mockups
return _stream.ReadAsync(buffer, offset, count, cancellationToken);
}
public Task WriteAsync(ArraySegment<byte> buffer, bool isEndOfPacket, CancellationToken cancellationToken)
public async Task WriteAsync(ReadOnlySequence<byte> buffer, bool isEndOfPacket, CancellationToken cancellationToken)
{
return _stream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count, cancellationToken);
foreach (var segment in buffer)
{
await _stream.WriteAsync(segment, cancellationToken).ConfigureAwait(false);
}
}
public void Dispose()
@@ -8,7 +8,6 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Internal;
namespace MQTTnet.Tests.Mockups
+21 -31
View File
@@ -9,9 +9,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Diagnostics;
using MQTTnet.Extensions.ManagedClient;
using MQTTnet.Diagnostics.Logger;
using MQTTnet.Extensions.Rpc;
using MQTTnet.Formatter;
using MQTTnet.Internal;
@@ -23,12 +21,12 @@ namespace MQTTnet.Tests.Mockups
{
public sealed class TestEnvironment : IDisposable
{
readonly List<string> _clientErrors = new List<string>();
readonly List<IMqttClient> _clients = new List<IMqttClient>();
readonly List<Exception> _exceptions = new List<Exception>();
readonly List<ILowLevelMqttClient> _lowLevelClients = new List<ILowLevelMqttClient>();
readonly List<string> _clientErrors = new();
readonly List<IMqttClient> _clients = new();
readonly List<Exception> _exceptions = new();
readonly List<ILowLevelMqttClient> _lowLevelClients = new();
readonly MqttProtocolVersion _protocolVersion;
readonly List<string> _serverErrors = new List<string>();
readonly List<string> _serverErrors = new();
public TestEnvironment() : this(null)
{
@@ -77,11 +75,13 @@ namespace MQTTnet.Tests.Mockups
};
}
public MqttNetEventLogger ClientLogger { get; } = new MqttNetEventLogger("client");
public MqttNetEventLogger ClientLogger { get; } = new("client");
public static bool EnableLogger { get; set; } = true;
public MqttFactory Factory { get; } = new MqttFactory();
public MqttClientFactory ClientFactory { get; } = new();
public MqttServerFactory ServerFactory { get; } = new();
public bool IgnoreClientLogErrors { get; set; }
@@ -89,7 +89,7 @@ namespace MQTTnet.Tests.Mockups
public MqttServer Server { get; private set; }
public MqttNetEventLogger ServerLogger { get; } = new MqttNetEventLogger("server");
public MqttNetEventLogger ServerLogger { get; } = new("server");
public int ServerPort { get; set; }
@@ -97,7 +97,7 @@ namespace MQTTnet.Tests.Mockups
public Task<IMqttClient> ConnectClient()
{
return ConnectClient(Factory.CreateClientOptionsBuilder().WithProtocolVersion(_protocolVersion));
return ConnectClient(ClientFactory.CreateClientOptionsBuilder().WithProtocolVersion(_protocolVersion));
}
public async Task<IMqttClient> ConnectClient(Action<MqttClientOptionsBuilder> configureOptions, TimeSpan timeout = default)
@@ -108,7 +108,7 @@ namespace MQTTnet.Tests.Mockups
}
// Start with initial default values.
var optionsBuilder = Factory.CreateClientOptionsBuilder().WithProtocolVersion(_protocolVersion).WithTcpServer("127.0.0.1", ServerPort);
var optionsBuilder = ClientFactory.CreateClientOptionsBuilder().WithProtocolVersion(_protocolVersion).WithTcpServer("127.0.0.1", ServerPort);
// Let the caller override settings. Do not touch the options after this.
configureOptions.Invoke(optionsBuilder);
@@ -204,21 +204,11 @@ namespace MQTTnet.Tests.Mockups
return new TestApplicationMessageReceivedHandler(mqttClient);
}
public TestApplicationMessageReceivedHandler CreateApplicationMessageHandler(IManagedMqttClient managedClient)
{
if (managedClient == null)
{
throw new ArgumentNullException(nameof(managedClient));
}
return new TestApplicationMessageReceivedHandler(managedClient.InternalClient);
}
public IMqttClient CreateClient()
{
var logger = EnableLogger ? (IMqttNetLogger)ClientLogger : MqttNetNullLogger.Instance;
var client = Factory.CreateMqttClient(logger);
var client = ClientFactory.CreateMqttClient(logger);
client.ConnectingAsync += e =>
{
@@ -250,7 +240,7 @@ namespace MQTTnet.Tests.Mockups
public MqttClientOptionsBuilder CreateDefaultClientOptionsBuilder()
{
return Factory.CreateClientOptionsBuilder()
return ClientFactory.CreateClientOptionsBuilder()
.WithProtocolVersion(_protocolVersion)
.WithTcpServer("127.0.0.1", ServerPort)
.WithClientId(TestContext.TestName + "_" + Guid.NewGuid());
@@ -258,7 +248,7 @@ namespace MQTTnet.Tests.Mockups
public ILowLevelMqttClient CreateLowLevelClient()
{
var client = Factory.CreateLowLevelMqttClient(ClientLogger);
var client = ClientFactory.CreateLowLevelMqttClient(ClientLogger);
lock (_lowLevelClients)
{
@@ -277,7 +267,7 @@ namespace MQTTnet.Tests.Mockups
var logger = EnableLogger ? (IMqttNetLogger)ServerLogger : new MqttNetNullLogger();
Server = Factory.CreateMqttServer(options, logger);
Server = ServerFactory.CreateMqttServer(options, logger);
Server.ValidatingConnectionAsync += e =>
{
@@ -352,7 +342,7 @@ namespace MQTTnet.Tests.Mockups
GC.Collect();
GC.WaitForFullGCComplete();
GC.WaitForPendingFinalizers();
if (_exceptions.Any())
{
throw new Exception($"{_exceptions.Count} exceptions tracked.\r\n" + string.Join(Environment.NewLine, _exceptions));
@@ -366,7 +356,7 @@ namespace MQTTnet.Tests.Mockups
public Task<MqttServer> StartServer()
{
return StartServer(Factory.CreateServerOptionsBuilder());
return StartServer(ServerFactory.CreateServerOptionsBuilder());
}
public async Task<MqttServer> StartServer(MqttServerOptionsBuilder optionsBuilder)
@@ -386,7 +376,7 @@ namespace MQTTnet.Tests.Mockups
public async Task<MqttServer> StartServer(Action<MqttServerOptionsBuilder> configure)
{
var optionsBuilder = Factory.CreateServerOptionsBuilder();
var optionsBuilder = ServerFactory.CreateServerOptionsBuilder();
optionsBuilder.WithDefaultEndpoint();
optionsBuilder.WithDefaultEndpointPort(ServerPort);
@@ -396,7 +386,7 @@ namespace MQTTnet.Tests.Mockups
var options = optionsBuilder.Build();
var server = CreateServer(options);
await server.StartAsync();
await server.StartAsync().ConfigureAwait(false);
// The OS has chosen the port to we have to properly expose it to the tests.
ServerPort = options.DefaultEndpointOptions.Port;
+1 -1
View File
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using MQTTnet.Diagnostics;
using MQTTnet.Diagnostics.Logger;
namespace MQTTnet.Tests.Mockups
{
@@ -4,7 +4,6 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Protocol;
@@ -30,7 +29,7 @@ namespace MQTTnet.Tests
Assert.AreEqual("xyz", message.Topic);
Assert.IsFalse(message.Retain);
Assert.AreEqual(MqttQualityOfServiceLevel.AtMostOnce, message.QualityOfServiceLevel);
Assert.AreEqual(Encoding.UTF8.GetString(message.PayloadSegment.ToArray()), "00:06:00");
Assert.AreEqual(Encoding.UTF8.GetString(message.Payload), "00:06:00");
}
[TestMethod]
@@ -42,7 +41,7 @@ namespace MQTTnet.Tests
Assert.AreEqual("123", message.Topic);
Assert.IsFalse(message.Retain);
Assert.AreEqual(MqttQualityOfServiceLevel.AtMostOnce, message.QualityOfServiceLevel);
Assert.AreEqual(Encoding.UTF8.GetString(message.PayloadSegment.ToArray()), "Hello");
Assert.AreEqual(Encoding.UTF8.GetString(message.Payload), "Hello");
}
[TestMethod]
@@ -1,45 +0,0 @@
#pragma warning disable CS0618 // Type or member is obsolete
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MQTTnet.Tests
{
[TestClass]
public sealed class MqttApplicationMessageTest
{
[TestMethod]
public void PayloadSegment()
{
var message = new MqttApplicationMessage();
Assert.AreEqual(0, message.Payload.Length);
Assert.AreEqual(0, message.PayloadSegment.Count);
Assert.IsTrue(ReferenceEquals(message.Payload, message.PayloadSegment.Array));
message.Payload = new byte[] { 1, 2 };
Assert.AreEqual(2, message.Payload.Length);
Assert.AreEqual(2, message.PayloadSegment.Count);
Assert.IsTrue(ReferenceEquals(message.Payload, message.PayloadSegment.Array));
message.Payload = new byte[] { 1, 2, 3 };
Assert.AreEqual(3, message.Payload.Length);
Assert.AreEqual(3, message.PayloadSegment.Count);
Assert.IsTrue(ReferenceEquals(message.Payload, message.PayloadSegment.Array));
message.PayloadSegment = new ArraySegment<byte>(new byte[] { 1, 2, 3 });
Assert.AreEqual(3, message.Payload.Length);
Assert.AreEqual(3, message.PayloadSegment.Count);
Assert.IsTrue(ReferenceEquals(message.Payload, message.PayloadSegment.Array));
message.PayloadSegment = new ArraySegment<byte>(new byte[] { 1, 2, 3 }, 1, 1);
Assert.AreEqual(1, message.Payload.Length);
Assert.AreEqual(1, message.PayloadSegment.Count);
Assert.IsFalse(ReferenceEquals(message.Payload, message.PayloadSegment.Array));
}
}
}
@@ -4,7 +4,6 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
namespace MQTTnet.Tests
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
namespace MQTTnet.Tests
{
@@ -1,7 +1,7 @@
using System;
using System.Threading;
using MQTTnet.Adapter;
using MQTTnet.Diagnostics;
using MQTTnet.Diagnostics.Logger;
using MQTTnet.Formatter;
using MQTTnet.Packets;
using MQTTnet.Tests.Mockups;
+1 -1
View File
@@ -39,7 +39,7 @@ namespace MQTTnet.Tests
}, ct.Token);
var clientSocket = new CrossPlatformSocket(AddressFamily.InterNetwork, ProtocolType.Tcp);
await clientSocket.ConnectAsync("localhost", 50001, CancellationToken.None);
await clientSocket.ConnectAsync(new DnsEndPoint("localhost", 50001), CancellationToken.None);
var tcpChannel = new MqttTcpChannel(clientSocket.GetStream(), "test", null);
+3 -4
View File
@@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Internal;
using MQTTnet.Tests.Mockups;
@@ -24,20 +23,20 @@ namespace MQTTnet.Tests
using (var testEnvironment = new TestEnvironment(TestContext))
{
await testEnvironment.StartServer();
var receiverClient = await testEnvironment.ConnectClient();
var senderClient = await testEnvironment.ConnectClient();
TaskCompletionSource<string> response = null;
receiverClient.ApplicationMessageReceivedAsync += e =>
receiverClient.ApplicationMessageReceivedAsync += e =>
{
response?.TrySetResult(e.ApplicationMessage.ConvertPayloadToString());
return CompletedTask.Instance;
};
await receiverClient.SubscribeAsync("#");
var times = new List<TimeSpan>();
var stopwatch = Stopwatch.StartNew();
@@ -5,7 +5,6 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Protocol;
@@ -49,7 +48,7 @@ namespace MQTTnet.Tests.Server
return CompletedTask.Instance;
};
testEnvironment.Server.ClientConnectedAsync += args =>
{
serverConnectedClientId = args.ClientId;
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
@@ -24,7 +25,7 @@ namespace MQTTnet.Tests.Server
await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithDefaultCommunicationTimeout(TimeSpan.FromSeconds(1)));
var client = new CrossPlatformSocket(AddressFamily.InterNetwork, ProtocolType.Tcp);
await client.ConnectAsync("localhost", testEnvironment.ServerPort, CancellationToken.None);
await client.ConnectAsync(new DnsEndPoint("localhost", testEnvironment.ServerPort), CancellationToken.None);
// Don't send anything. The server should close the connection.
await Task.Delay(TimeSpan.FromSeconds(3));
@@ -55,7 +56,7 @@ namespace MQTTnet.Tests.Server
// 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, ProtocolType.Tcp);
await client.ConnectAsync("localhost", testEnvironment.ServerPort, CancellationToken.None);
await client.ConnectAsync(new DnsEndPoint("localhost", testEnvironment.ServerPort), CancellationToken.None);
var buffer = Encoding.UTF8.GetBytes("Garbage");
await client.SendAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
@@ -2,7 +2,6 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
namespace MQTTnet.Tests.Server
@@ -44,7 +43,7 @@ namespace MQTTnet.Tests.Server
var receiver = await testEnvironment.ConnectClient(o => o.WithProtocolVersion(MqttProtocolVersion.V311));
var receivedApplicationMessages = testEnvironment.CreateApplicationMessageHandler(receiver);
await receiver.SubscribeAsync("#");
var sender = await testEnvironment.ConnectClient();
var applicationMessage = new MqttApplicationMessageBuilder().WithTopic("My/Message")
@@ -53,7 +52,7 @@ namespace MQTTnet.Tests.Server
.WithResponseTopic("Response")
.WithCorrelationData(Encoding.UTF8.GetBytes("Correlation"))
.Build();
await sender.PublishAsync(applicationMessage);
await LongTestDelay();
+30 -31
View File
@@ -5,7 +5,6 @@
using System;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Protocol;
@@ -31,11 +30,11 @@ namespace MQTTnet.Tests.Server
};
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);
@@ -59,17 +58,17 @@ namespace MQTTnet.Tests.Server
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()
{
@@ -86,70 +85,70 @@ namespace MQTTnet.Tests.Server
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();
ClientUnsubscribedTopicEventArgs eventArgs = null;
server.ClientUnsubscribedTopicAsync += e =>
{
eventArgs = e;
return CompletedTask.Instance;
};
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();
InterceptingPublishEventArgs eventArgs = null;
server.InterceptingPublishAsync += e =>
{
eventArgs = e;
return CompletedTask.Instance;
};
var client = await testEnvironment.ConnectClient();
await client.PublishStringAsync("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()
{
@@ -163,22 +162,22 @@ namespace MQTTnet.Tests.Server
eventArgs = e;
return CompletedTask.Instance;
};
await server.StartAsync();
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.StoppedAsync += e =>
{
@@ -187,9 +186,9 @@ namespace MQTTnet.Tests.Server
};
await server.StopAsync();
await LongTestDelay();
Assert.IsNotNull(eventArgs);
}
}
+15 -14
View File
@@ -2,19 +2,18 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Internal;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using MQTTnet.Server;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Adapter;
using MQTTnet.Client;
using MQTTnet.Internal;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using MQTTnet.Server;
namespace MQTTnet.Tests.Server
{
@@ -60,7 +59,7 @@ namespace MQTTnet.Tests.Server
var server = await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithPersistentSessions());
// Create the session including the subscription.
var client1 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("a").WithCleanSession(false));
var client1 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("a").WithCleanSession(false).WithSessionExpiryInterval(60));
await client1.SubscribeAsync("x");
await client1.DisconnectAsync();
await Task.Delay(500);
@@ -68,7 +67,7 @@ namespace MQTTnet.Tests.Server
var clientStatus = await server.GetClientsAsync();
Assert.AreEqual(0, clientStatus.Count);
var client2 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("b").WithCleanSession(false));
var client2 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("b").WithCleanSession(false).WithSessionExpiryInterval(60));
await client2.PublishStringAsync("x", "1");
await client2.PublishStringAsync("x", "2");
await client2.PublishStringAsync("x", "3");
@@ -101,8 +100,10 @@ namespace MQTTnet.Tests.Server
return CompletedTask.Instance;
};
var connectingFailedException = await Assert.ThrowsExceptionAsync<MqttConnectingFailedException>(() => testEnvironment.ConnectClient());
Assert.AreEqual(MqttClientConnectResultCode.NotAuthorized, connectingFailedException.ResultCode);
var client = testEnvironment.CreateClient();
var response = await client.ConnectAsync(testEnvironment.CreateDefaultClientOptions());
Assert.AreEqual(MqttClientConnectResultCode.NotAuthorized, response.ResultCode);
}
}
@@ -314,7 +315,7 @@ namespace MQTTnet.Tests.Server
var isIntercepted = false;
c2.ApplicationMessageReceivedAsync += e =>
{
isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment.ToArray()), StringComparison.Ordinal) == 0;
isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(e.ApplicationMessage.Payload), StringComparison.Ordinal) == 0;
return CompletedTask.Instance;
};
@@ -780,7 +781,7 @@ namespace MQTTnet.Tests.Server
var client1 = await testEnvironment.ConnectClient();
client1.ApplicationMessageReceivedAsync += e =>
{
receivedBody = e.ApplicationMessage.PayloadSegment.ToArray();
receivedBody = e.ApplicationMessage.Payload.ToArray();
return CompletedTask.Instance;
};
@@ -794,7 +795,7 @@ namespace MQTTnet.Tests.Server
Assert.IsTrue(longBody.SequenceEqual(receivedBody ?? new byte[0]));
}
}
[TestMethod]
public async Task Set_Subscription_At_Server()
{
@@ -1,4 +1,3 @@
#if !(NET452 || NET461 || NET48)
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
@@ -12,7 +11,6 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Certificates;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Protocol;
using MQTTnet.Server;
@@ -239,7 +237,7 @@ namespace MQTTnet.Tests.Server
var mqttClientOptions = optionsBuilder.Build();
var factory = new MqttFactory();
var factory = new MqttClientFactory();
var mqttClient = factory.CreateMqttClient();
_client = mqttClient;
@@ -295,7 +293,7 @@ namespace MQTTnet.Tests.Server
public Task StartServer()
{
var mqttFactory = new MqttFactory();
var mqttServerFactory = new MqttServerFactory();
var mqttServerOptions = new MqttServerOptionsBuilder().WithEncryptionCertificate(_hotSwapServer)
.WithRemoteCertificateValidationCallback(_hotSwapServer.RemoteCertificateValidationCallback)
@@ -304,7 +302,7 @@ namespace MQTTnet.Tests.Server
mqttServerOptions.TlsEndpointOptions.ClientCertificateRequired = true;
_server = mqttFactory.CreateMqttServer(mqttServerOptions);
_server = mqttServerFactory.CreateMqttServer(mqttServerOptions);
return _server.StartAsync();
}
}
@@ -318,16 +316,14 @@ namespace MQTTnet.Tests.Server
{
_certificates = new X509Certificate2Collection(CreateSelfSignedCertificate("1.3.6.1.5.5.7.3.2"));
}
public void Dispose()
{
if (_certificates != null)
{
foreach (var certs in _certificates)
{
#if !NET452
certs.Dispose();
#endif
}
}
}
@@ -378,9 +374,7 @@ namespace MQTTnet.Tests.Server
public void Dispose()
{
#if !NET452
_certificate.Dispose();
#endif
}
public X509Certificate2 GetCertificate()
@@ -392,9 +386,8 @@ namespace MQTTnet.Tests.Server
{
var newCert = CreateSelfSignedCertificate("1.3.6.1.5.5.7.3.1");
var oldCert = Interlocked.Exchange(ref _certificate, newCert);
#if !NET452
oldCert.Dispose();
#endif
}
public void InstallNewClientCert(X509Certificate2 certificate)
@@ -422,5 +415,3 @@ namespace MQTTnet.Tests.Server
}
}
}
#endif
@@ -1,6 +1,5 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Internal;
using MQTTnet.Server;
+7 -8
View File
@@ -2,7 +2,6 @@ using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Internal;
using MQTTnet.Packets;
using MQTTnet.Protocol;
@@ -76,7 +75,7 @@ namespace MQTTnet.Tests.Server
Interlocked.Increment(ref receivedMessages);
return CompletedTask.Instance;
};
for (var i = 0; i < 100; i++)
{
_ = Task.Run(
@@ -95,12 +94,12 @@ namespace MQTTnet.Tests.Server
var packet = await client.ReceiveAsync(CancellationToken.None);
var connAckPacket = packet as MqttConnAckPacket;
Assert.IsTrue(connAckPacket != null);
Assert.AreEqual(MqttConnectReasonCode.Success, connAckPacket.ReasonCode);
var publishPacket = new MqttPublishPacket();
for (var j = 0; j < 1000; j++)
{
publishPacket.Topic = j.ToString();
@@ -108,7 +107,7 @@ namespace MQTTnet.Tests.Server
await client.SendAsync(publishPacket, CancellationToken.None)
.ConfigureAwait(false);
}
await client.DisconnectAsync(CancellationToken.None);
}
}
@@ -124,7 +123,7 @@ namespace MQTTnet.Tests.Server
Assert.AreEqual(100000, receivedMessages);
}
}
[TestMethod]
public async Task Handle_100_000_Messages_In_Server()
{
@@ -148,7 +147,7 @@ namespace MQTTnet.Tests.Server
using (var client = await testEnvironment.ConnectClient())
{
var applicationMessageBuilder = new MqttApplicationMessageBuilder();
for (var j = 0; j < 1000; j++)
{
var message = applicationMessageBuilder.WithTopic(j.ToString())
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MQTTnet.Server.Internal;
namespace MQTTnet.Tests.Server
{
@@ -14,8 +15,8 @@ namespace MQTTnet.Tests.Server
public async Task MqttRetainedMessageManager_GetUndefinedTopic()
{
var logger = new Mockups.TestLogger();
var eventContainer = new MQTTnet.Server.MqttServerEventContainer();
var retainedMessagesManager = new MQTTnet.Server.MqttRetainedMessagesManager(eventContainer, logger);
var eventContainer = new MqttServerEventContainer();
var retainedMessagesManager = new MqttRetainedMessagesManager(eventContainer, logger);
var task = retainedMessagesManager.GetMessage("undefined");
Assert.IsNotNull(task, "Task should not be null");
var result = await task;
@@ -10,6 +10,7 @@ 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
@@ -4,7 +4,6 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
namespace MQTTnet.Tests.Server
@@ -17,7 +16,7 @@ namespace MQTTnet.Tests.Server
{
return ExecuteTest(true, 0);
}
[TestMethod]
public Task Subscribe_Without_No_Local()
{
@@ -31,19 +30,19 @@ namespace MQTTnet.Tests.Server
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();
var topicFilter = testEnvironment.ClientFactory.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.PublishStringAsync("Topic", "Payload", retain: true);
await LongTestDelay();
applicationMessageHandler.AssertReceivedCountEquals(expectedCountAfterPublish);
}
}
@@ -4,7 +4,7 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Protocol;
@@ -79,29 +79,29 @@ namespace MQTTnet.Tests.Server
using (var testEnvironment = CreateTestEnvironment())
{
var server = await testEnvironment.StartServer();
var sender = await testEnvironment.ConnectClient();
var receiver = await testEnvironment.ConnectClient();
await receiver.SubscribeAsync("A");
var receivedMessages = testEnvironment.CreateApplicationMessageHandler(receiver);
await sender.PublishStringAsync("A", "Payload", MqttQualityOfServiceLevel.AtLeastOnce);
await LongTestDelay();
receivedMessages.AssertReceivedCountEquals(1);
server.InterceptingClientEnqueueAsync += e =>
{
e.AcceptEnqueue = false;
return CompletedTask.Instance;
};
await sender.PublishStringAsync("A", "Payload", MqttQualityOfServiceLevel.AtLeastOnce);
await LongTestDelay();
// Do not increase because the internal enqueue to the target client is not accepted!
receivedMessages.AssertReceivedCountEquals(1);
}
+116 -118
View File
@@ -5,165 +5,163 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Internal;
using MQTTnet.Protocol;
using MQTTnet.Server;
namespace MQTTnet.Tests.Server
namespace MQTTnet.Tests.Server;
[TestClass]
public sealed class QoS_Tests : BaseTestClass
{
[TestClass]
public sealed class QoS_Tests : BaseTestClass
[TestMethod]
public async Task Fire_Event_On_Client_Acknowledges_QoS_0()
{
[TestMethod]
public async Task Preserve_Message_Order_For_Queued_Messages()
using (var testEnvironment = CreateTestEnvironment())
{
using (var testEnvironment = CreateTestEnvironment())
var server = await testEnvironment.StartServer();
ClientAcknowledgedPublishPacketEventArgs eventArgs = null;
server.ClientAcknowledgedPublishPacketAsync += args =>
{
var server = await testEnvironment.StartServer(o => o.WithPersistentSessions());
eventArgs = args;
return CompletedTask.Instance;
};
// Create a session which will contain the messages.
var dummyClient = await testEnvironment.ConnectClient(o => o.WithClientId("A").WithCleanSession(false));
await dummyClient.SubscribeAsync("#", MqttQualityOfServiceLevel.AtLeastOnce);
dummyClient.Dispose();
var client1 = await testEnvironment.ConnectClient();
await client1.SubscribeAsync("A");
await LongTestDelay();
await LongTestDelay();
// Now inject messages which are appended to the queue of the client.
await server.InjectApplicationMessage("T", "0", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "2", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "1", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "4", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "3", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "6", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "5", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "8", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "7", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "9", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
await LongTestDelay();
// Create a new client for the existing message.
var client = await testEnvironment.ConnectClient(o => o.WithClientId("A").WithCleanSession(false));
var messages = testEnvironment.CreateApplicationMessageHandler(client);
await LongTestDelay();
var payloadSequence = messages.GeneratePayloadSequence();
Assert.AreEqual("0214365879", payloadSequence);
var client2 = await testEnvironment.ConnectClient();
await client2.PublishStringAsync("A");
// Disconnect and reconnect to make sure that the server will not send the messages twice.
await client.DisconnectAsync();
await LongTestDelay();
await client.ReconnectAsync();
await LongTestDelay();
payloadSequence = messages.GeneratePayloadSequence();
Assert.AreEqual("0214365879", payloadSequence);
}
await LongTestDelay();
// Must be null because no event should be fired for QoS 0.
Assert.IsNull(eventArgs);
}
[TestMethod]
public async Task Fire_Event_On_Client_Acknowledges_QoS_0()
}
[TestMethod]
public async Task Fire_Event_On_Client_Acknowledges_QoS_1()
{
using (var testEnvironment = CreateTestEnvironment())
{
using (var testEnvironment = CreateTestEnvironment())
var server = await testEnvironment.StartServer();
ClientAcknowledgedPublishPacketEventArgs eventArgs = null;
server.ClientAcknowledgedPublishPacketAsync += args =>
{
var server = await testEnvironment.StartServer();
eventArgs = args;
return CompletedTask.Instance;
};
ClientAcknowledgedPublishPacketEventArgs eventArgs = null;
server.ClientAcknowledgedPublishPacketAsync += args =>
{
eventArgs = args;
return CompletedTask.Instance;
};
var client1 = await testEnvironment.ConnectClient();
await client1.SubscribeAsync("A", MqttQualityOfServiceLevel.AtLeastOnce);
var client1 = await testEnvironment.ConnectClient();
await client1.SubscribeAsync("A");
var client2 = await testEnvironment.ConnectClient();
await client2.PublishStringAsync("A", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
var client2 = await testEnvironment.ConnectClient();
await client2.PublishStringAsync("A");
await LongTestDelay();
await LongTestDelay();
Assert.IsNotNull(eventArgs);
Assert.IsNotNull(eventArgs.PublishPacket);
Assert.IsNotNull(eventArgs.AcknowledgePacket);
Assert.IsTrue(eventArgs.IsCompleted);
// Must be null because no event should be fired for QoS 0.
Assert.IsNull(eventArgs);
}
Assert.AreEqual("A", eventArgs.PublishPacket.Topic);
}
}
[TestMethod]
public async Task Fire_Event_On_Client_Acknowledges_QoS_1()
[TestMethod]
public async Task Fire_Event_On_Client_Acknowledges_QoS_2()
{
using (var testEnvironment = CreateTestEnvironment())
{
using (var testEnvironment = CreateTestEnvironment())
var server = await testEnvironment.StartServer();
var eventArgs = new List<ClientAcknowledgedPublishPacketEventArgs>();
server.ClientAcknowledgedPublishPacketAsync += args =>
{
var server = await testEnvironment.StartServer();
ClientAcknowledgedPublishPacketEventArgs eventArgs = null;
server.ClientAcknowledgedPublishPacketAsync += args =>
lock (eventArgs)
{
eventArgs = args;
return CompletedTask.Instance;
};
eventArgs.Add(args);
}
var client1 = await testEnvironment.ConnectClient();
await client1.SubscribeAsync("A", MqttQualityOfServiceLevel.AtLeastOnce);
return CompletedTask.Instance;
};
var client2 = await testEnvironment.ConnectClient();
await client2.PublishStringAsync("A", qualityOfServiceLevel: MqttQualityOfServiceLevel.AtLeastOnce);
var client1 = await testEnvironment.ConnectClient();
await client1.SubscribeAsync("A", MqttQualityOfServiceLevel.ExactlyOnce);
await LongTestDelay();
var client2 = await testEnvironment.ConnectClient();
await client2.PublishStringAsync("A", qualityOfServiceLevel: MqttQualityOfServiceLevel.ExactlyOnce);
Assert.IsNotNull(eventArgs);
Assert.IsNotNull(eventArgs.PublishPacket);
Assert.IsNotNull(eventArgs.AcknowledgePacket);
Assert.IsTrue(eventArgs.IsCompleted);
await LongTestDelay();
Assert.AreEqual("A", eventArgs.PublishPacket.Topic);
}
Assert.AreEqual(1, eventArgs.Count);
var firstEvent = eventArgs[0];
Assert.IsNotNull(firstEvent);
Assert.IsNotNull(firstEvent.PublishPacket);
Assert.IsNotNull(firstEvent.AcknowledgePacket);
Assert.IsTrue(firstEvent.IsCompleted);
Assert.AreEqual("A", firstEvent.PublishPacket.Topic);
}
}
[TestMethod]
public async Task Fire_Event_On_Client_Acknowledges_QoS_2()
[TestMethod]
public async Task Preserve_Message_Order_For_Queued_Messages()
{
using (var testEnvironment = CreateTestEnvironment())
{
using (var testEnvironment = CreateTestEnvironment())
{
var server = await testEnvironment.StartServer();
var server = await testEnvironment.StartServer(o => o.WithPersistentSessions());
var eventArgs = new List<ClientAcknowledgedPublishPacketEventArgs>();
server.ClientAcknowledgedPublishPacketAsync += args =>
{
lock (eventArgs)
{
eventArgs.Add(args);
}
// Create a session which will contain the messages.
var dummyClient = await testEnvironment.ConnectClient(o => o.WithClientId("A").WithCleanSession(false));
await dummyClient.SubscribeAsync("#", MqttQualityOfServiceLevel.AtLeastOnce);
dummyClient.Dispose();
return CompletedTask.Instance;
};
await LongTestDelay();
await LongTestDelay();
var client1 = await testEnvironment.ConnectClient();
await client1.SubscribeAsync("A", MqttQualityOfServiceLevel.ExactlyOnce);
// Now inject messages which are appended to the queue of the client.
await server.InjectApplicationMessage("T", "0", MqttQualityOfServiceLevel.AtLeastOnce);
var client2 = await testEnvironment.ConnectClient();
await client2.PublishStringAsync("A", qualityOfServiceLevel: MqttQualityOfServiceLevel.ExactlyOnce);
await server.InjectApplicationMessage("T", "2", MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "1", MqttQualityOfServiceLevel.AtLeastOnce);
await LongTestDelay();
await server.InjectApplicationMessage("T", "4", MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "3", MqttQualityOfServiceLevel.AtLeastOnce);
Assert.AreEqual(1, eventArgs.Count);
await server.InjectApplicationMessage("T", "6", MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "5", MqttQualityOfServiceLevel.AtLeastOnce);
var firstEvent = eventArgs[0];
await server.InjectApplicationMessage("T", "8", MqttQualityOfServiceLevel.AtLeastOnce);
await server.InjectApplicationMessage("T", "7", MqttQualityOfServiceLevel.AtLeastOnce);
Assert.IsNotNull(firstEvent);
Assert.IsNotNull(firstEvent.PublishPacket);
Assert.IsNotNull(firstEvent.AcknowledgePacket);
Assert.IsTrue(firstEvent.IsCompleted);
await server.InjectApplicationMessage("T", "9", MqttQualityOfServiceLevel.AtLeastOnce);
Assert.AreEqual("A", firstEvent.PublishPacket.Topic);
}
await LongTestDelay();
// Create a new client for the existing message.
var client = await testEnvironment.ConnectClient(o => o.WithClientId("A").WithCleanSession(false));
var messages = testEnvironment.CreateApplicationMessageHandler(client);
await LongTestDelay();
var payloadSequence = messages.GeneratePayloadSequence();
Assert.AreEqual("0214365879", payloadSequence);
// Disconnect and reconnect to make sure that the server will not send the messages twice.
await client.DisconnectAsync();
await LongTestDelay();
await client.ReconnectAsync();
await LongTestDelay();
payloadSequence = messages.GeneratePayloadSequence();
Assert.AreEqual("0214365879", payloadSequence);
}
}
}
@@ -5,7 +5,6 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Formatter;
using MQTTnet.Client;
namespace MQTTnet.Tests.Server
{
@@ -32,7 +31,7 @@ namespace MQTTnet.Tests.Server
var client1 = await testEnvironment.ConnectClient();
var applicationMessageHandler = testEnvironment.CreateApplicationMessageHandler(client1);
var topicFilter = testEnvironment.Factory.CreateTopicFilterBuilder().WithTopic("Topic").WithRetainAsPublished(retainAsPublished).Build();
var topicFilter = testEnvironment.ClientFactory.CreateTopicFilterBuilder().WithTopic("Topic").WithRetainAsPublished(retainAsPublished).Build();
await client1.SubscribeAsync(topicFilter);
await LongTestDelay();
@@ -4,7 +4,6 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Protocol;
@@ -18,13 +17,13 @@ namespace MQTTnet.Tests.Server
{
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()
{
@@ -45,21 +44,21 @@ namespace MQTTnet.Tests.Server
await client1.PublishStringAsync("Topic", "Payload", retain: true);
await LongTestDelay();
var client2 = await testEnvironment.ConnectClient();
var applicationMessageHandler = testEnvironment.CreateApplicationMessageHandler(client2);
var topicFilter = testEnvironment.Factory.CreateTopicFilterBuilder().WithTopic("Topic").WithRetainHandling(retainHandling).Build();
var topicFilter = testEnvironment.ClientFactory.CreateTopicFilterBuilder().WithTopic("Topic").WithRetainHandling(retainHandling).Build();
await client2.SubscribeAsync(topicFilter);
await LongTestDelay();
applicationMessageHandler.AssertReceivedCountEquals(expectedCountAfterSubscribe);
await client1.PublishStringAsync("Topic", "Payload", retain: true);
await LongTestDelay();
applicationMessageHandler.AssertReceivedCountEquals(expectedCountAfterSecondPublish);
await client2.SubscribeAsync(topicFilter);
await LongTestDelay();
@@ -5,7 +5,6 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Packets;
using MQTTnet.Protocol;
@@ -242,7 +241,7 @@ namespace MQTTnet.Tests.Server
var client = testEnvironment.CreateClient();
var connectResult = await client.ConnectAsync(
testEnvironment.Factory.CreateClientOptionsBuilder()
testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithProtocolVersion(MqttProtocolVersion.V311)
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.Build());
@@ -260,7 +259,7 @@ namespace MQTTnet.Tests.Server
var client = testEnvironment.CreateClient();
var connectResult = await client.ConnectAsync(
testEnvironment.Factory.CreateClientOptionsBuilder()
testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithProtocolVersion(MqttProtocolVersion.V500)
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.Build());
+10 -12
View File
@@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Adapter;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Internal;
using MQTTnet.Protocol;
@@ -22,7 +21,7 @@ namespace MQTTnet.Tests.Server
using (var testEnvironment = CreateTestEnvironment())
{
testEnvironment.IgnoreClientLogErrors = true;
await testEnvironment.StartServer();
var publishedApplicationMessages = new List<MqttApplicationMessage>();
@@ -53,7 +52,7 @@ namespace MQTTnet.Tests.Server
using (var validClient = testEnvironment.CreateClient())
{
await validClient.ConnectAsync(
testEnvironment.Factory.CreateClientOptionsBuilder()
testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithTcpServer("localhost", testEnvironment.ServerPort)
.WithCredentials("SECRET")
.WithClientId("CLIENT")
@@ -68,7 +67,7 @@ namespace MQTTnet.Tests.Server
using (var invalidClient = testEnvironment.CreateClient())
{
await invalidClient.ConnectAsync(
testEnvironment.Factory.CreateClientOptionsBuilder()
testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithTcpServer("localhost", testEnvironment.ServerPort)
.WithCredentials("???")
.WithClientId("CLIENT")
@@ -81,15 +80,15 @@ namespace MQTTnet.Tests.Server
}
await LongTestDelay();
await validClient.PublishStringAsync("HELLO 2");
await LongTestDelay();
await validClient.PublishStringAsync("HELLO 3");
await LongTestDelay();
Assert.AreEqual(3, publishedApplicationMessages.Count);
Assert.AreEqual(1, testEnvironment.Server.GetClientsAsync().GetAwaiter().GetResult().Count);
}
@@ -133,7 +132,6 @@ namespace MQTTnet.Tests.Server
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);
Assert.AreEqual(MqttClientConnectResultCode.UnspecifiedError, ex.ResultCode);
}
}
@@ -164,8 +162,8 @@ namespace MQTTnet.Tests.Server
var clientOptions = new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).WithCredentials(userName, password).Build();
var ex = await Assert.ThrowsExceptionAsync<MqttConnectingFailedException>(() => client.ConnectAsync(clientOptions));
Assert.AreEqual(MqttClientConnectResultCode.BadUserNameOrPassword, ex.Result.ResultCode);
var response = await client.ConnectAsync(clientOptions);
Assert.AreEqual(MqttClientConnectResultCode.BadUserNameOrPassword, response.ResultCode);
}
}
}
@@ -4,51 +4,38 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Adapter;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Implementations;
using MQTTnet.Internal;
using MQTTnet.Protocol;
namespace MQTTnet.Tests.Server
namespace MQTTnet.Tests.Server;
[TestClass]
public sealed class Server_Reference_Tests : BaseTestClass
{
[TestClass]
public sealed class Server_Reference_Tests : BaseTestClass
[TestMethod]
public async Task Server_Reports_With_Reference_Server()
{
[TestMethod]
public async Task Server_Reports_With_Reference_Server()
using (var testEnvironment = CreateTestEnvironment())
{
using (var testEnvironment = CreateTestEnvironment())
testEnvironment.IgnoreClientLogErrors = true;
var server = await testEnvironment.StartServer();
server.ValidatingConnectionAsync += e =>
{
testEnvironment.IgnoreClientLogErrors = true;
var server = await testEnvironment.StartServer();
e.ReasonCode = MqttConnectReasonCode.ServerMoved;
e.ServerReference = "new_server";
return CompletedTask.Instance;
};
server.ValidatingConnectionAsync += e =>
{
e.ReasonCode = MqttConnectReasonCode.ServerMoved;
e.ServerReference = "new_server";
return CompletedTask.Instance;
};
var client = testEnvironment.CreateClient();
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);
}
}
var response = await client.ConnectAsync(
new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500).WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
Assert.AreEqual(MqttClientConnectResultCode.ServerMoved, response.ResultCode);
Assert.AreEqual("new_server", response.ServerReference);
}
}
}
+1 -2
View File
@@ -8,7 +8,6 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Protocol;
@@ -51,7 +50,7 @@ namespace MQTTnet.Tests.Server
// Reconnect the same client ID without clean session
var client2 = testEnvironment.CreateClient();
var options = testEnvironment.Factory.CreateClientOptionsBuilder()
var options = testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithProtocolVersion(MqttProtocolVersion.V311)
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.WithSessionExpiryInterval(9999) // not relevant for v311 but testing impact
@@ -5,7 +5,6 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
namespace MQTTnet.Tests.Server
@@ -21,14 +20,14 @@ namespace MQTTnet.Tests.Server
await testEnvironment.StartServer();
var client = testEnvironment.CreateClient();
var connectResult = await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
var connectResult = await client.ConnectAsync(testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithProtocolVersion(MqttProtocolVersion.V500)
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
Assert.IsFalse(connectResult.SharedSubscriptionAvailable);
}
}
[TestMethod]
public async Task Subscription_Of_Shared_Subscription_Is_Denied()
{
@@ -37,12 +36,12 @@ namespace MQTTnet.Tests.Server
await testEnvironment.StartServer();
var client = testEnvironment.CreateClient();
await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
await client.ConnectAsync(testEnvironment.ClientFactory.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.First().ResultCode);
}
}
+180 -143
View File
@@ -5,159 +5,196 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Protocol;
using MQTTnet.Server;
using MQTTnet.Tests.Mockups;
namespace MQTTnet.Tests.Server
namespace MQTTnet.Tests.Server;
[TestClass]
public sealed class Status_Tests : BaseTestClass
{
[TestClass]
public sealed class Status_Tests : BaseTestClass
[TestMethod]
public async Task Disconnect_Client()
{
[TestMethod]
public async Task Show_Client_And_Session_Statistics()
using (var testEnvironment = new TestEnvironment(TestContext))
{
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.GetClientsAsync();
Assert.AreEqual(1, clientStatus.Count);
Assert.IsTrue(clientStatus.Any(s => s.Id == c1.Options.ClientId));
await clientStatus.First().DisconnectAsync();
await Task.Delay(500);
Assert.IsFalse(c1.IsConnected);
clientStatus = await server.GetClientsAsync();
Assert.AreEqual(0, clientStatus.Count);
}
}
[TestMethod]
public async Task Keep_Persistent_Session_Version311()
{
using (var testEnvironment = new TestEnvironment(TestContext))
{
var server = await testEnvironment.StartServer(o => o.WithPersistentSessions());
var c1 = await testEnvironment.ConnectClient(
new MqttClientOptionsBuilder().WithClientId("client1").WithCleanSession(false).WithProtocolVersion(MqttProtocolVersion.V311));
var c2 = await testEnvironment.ConnectClient(
new MqttClientOptionsBuilder().WithClientId("client2").WithCleanSession(false).WithProtocolVersion(MqttProtocolVersion.V311));
await c1.DisconnectAsync();
await LongTestDelay();
var clientStatus = await server.GetClientsAsync();
var sessionStatus = await server.GetSessionsAsync();
Assert.AreEqual(1, clientStatus.Count);
Assert.AreEqual(2, sessionStatus.Count);
await c2.DisconnectAsync();
await LongTestDelay();
clientStatus = await server.GetClientsAsync();
sessionStatus = await server.GetSessionsAsync();
Assert.AreEqual(0, clientStatus.Count);
Assert.AreEqual(2, sessionStatus.Count);
}
}
[TestMethod]
public async Task Keep_Persistent_Session_Version500()
{
using (var testEnvironment = new TestEnvironment(TestContext))
{
var server = await testEnvironment.StartServer(o => o.WithPersistentSessions());
var c1 = await testEnvironment.ConnectClient(
new MqttClientOptionsBuilder().WithClientId("client1").WithCleanSession(false).WithProtocolVersion(MqttProtocolVersion.V500));
var c2 = await testEnvironment.ConnectClient(
new MqttClientOptionsBuilder().WithClientId("client2").WithCleanSession(false).WithProtocolVersion(MqttProtocolVersion.V500));
// The session expiry interval is mandatory for MQTT5.0.0 in order keep session!
await c1.DisconnectAsync(sessionExpiryInterval: 60);
await LongTestDelay();
var clientStatus = await server.GetClientsAsync();
var sessionStatus = await server.GetSessionsAsync();
Assert.AreEqual(1, clientStatus.Count);
Assert.AreEqual(2, sessionStatus.Count);
// The session expiry interval is mandatory for MQTT5.0.0 in order keep session!
await c2.DisconnectAsync(sessionExpiryInterval: 60);
await LongTestDelay();
clientStatus = await server.GetClientsAsync();
sessionStatus = await server.GetSessionsAsync();
Assert.AreEqual(0, clientStatus.Count);
Assert.AreEqual(2, sessionStatus.Count);
}
}
[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.GetClientsAsync();
var sessionStatus = await server.GetSessionsAsync();
Assert.AreEqual(2, clientStatus.Count);
Assert.AreEqual(2, sessionStatus.Count);
Assert.IsTrue(clientStatus.Any(s => s.Id == c1.Options.ClientId));
Assert.IsTrue(clientStatus.Any(s => s.Id == c2.Options.ClientId));
await c1.DisconnectAsync();
await c2.DisconnectAsync();
await Task.Delay(500);
clientStatus = await server.GetClientsAsync();
sessionStatus = await server.GetSessionsAsync();
Assert.AreEqual(0, clientStatus.Count);
Assert.AreEqual(0, 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++)
{
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);
await c1.PublishStringAsync("a");
await Task.Delay(50);
var clientStatus = await server.GetClientsAsync();
var sessionStatus = await server.GetSessionsAsync();
Assert.AreEqual(2, clientStatus.Count);
Assert.AreEqual(2, sessionStatus.Count);
Assert.IsTrue(clientStatus.Any(s => s.Id == c1.Options.ClientId));
Assert.IsTrue(clientStatus.Any(s => s.Id == c2.Options.ClientId));
await c1.DisconnectAsync();
await c2.DisconnectAsync();
await Task.Delay(500);
clientStatus = await server.GetClientsAsync();
sessionStatus = await server.GetSessionsAsync();
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.GetClientsAsync();
Assert.AreEqual(1, clientStatus.Count);
Assert.IsTrue(clientStatus.Any(s => s.Id == c1.Options.ClientId));
await clientStatus.First().DisconnectAsync();
await Task.Delay(500);
Assert.IsFalse(c1.IsConnected);
clientStatus = await server.GetClientsAsync();
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").WithCleanSession(false));
var c2 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("client2").WithCleanSession(false));
await c1.DisconnectAsync();
await Task.Delay(500);
var clientStatus = await server.GetClientsAsync();
var sessionStatus = await server.GetSessionsAsync();
Assert.AreEqual(1, clientStatus.Count);
Assert.AreEqual(2, sessionStatus.Count);
await c2.DisconnectAsync();
await Task.Delay(500);
clientStatus = await server.GetClientsAsync();
sessionStatus = await server.GetSessionsAsync();
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.PublishStringAsync("a");
await Task.Delay(50);
var clientStatus = await server.GetClientsAsync();
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.PublishStringAsync("a", string.Empty, MqttQualityOfServiceLevel.AtLeastOnce);
await Task.Delay(500);
var clientStatus = await server.GetClientsAsync();
Assert.AreEqual(i, clientStatus.First().SentApplicationMessagesCount, "SAMC invalid!");
// + 1 because CONNECT is also counted.
Assert.AreEqual(i + 1, clientStatus.First().SentPacketsCount, "SPC invalid!");
// +2 because ConnACK + PubAck package is already counted.
Assert.AreEqual(i + 2, clientStatus.First().ReceivedPacketsCount, "RPC invalid!");
}
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.PublishStringAsync("a", string.Empty, MqttQualityOfServiceLevel.AtLeastOnce);
await Task.Delay(500);
var clientStatus = await server.GetClientsAsync();
Assert.AreEqual(i, clientStatus.First().SentApplicationMessagesCount, "SAMC invalid!");
// + 1 because CONNECT is also counted.
Assert.AreEqual(i + 1, clientStatus.First().SentPacketsCount, "SPC invalid!");
// +2 because ConnACK + PubAck package is already counted.
Assert.AreEqual(i + 2, clientStatus.First().ReceivedPacketsCount, "RPC invalid!");
}
}
}
}
@@ -7,7 +7,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Packets;
@@ -106,7 +106,7 @@ namespace MQTTnet.Tests.Server
var client = await testEnvironment.ConnectClient();
var subscribeOptions = testEnvironment.Factory.CreateSubscribeOptionsBuilder().WithTopicFilter("X").WithUserProperty("A", "1").Build();
var subscribeOptions = testEnvironment.ClientFactory.CreateSubscribeOptionsBuilder().WithTopicFilter("X").WithUserProperty("A", "1").Build();
await client.SubscribeAsync(subscribeOptions);
CollectionAssert.AreEqual(subscribeOptions.UserProperties.ToList(), eventArgs.UserProperties);
@@ -4,7 +4,6 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
namespace MQTTnet.Tests.Server
@@ -18,33 +17,33 @@ namespace MQTTnet.Tests.Server
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
{
await testEnvironment.StartServer();
var client = testEnvironment.CreateClient();
var connectResult = await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
var connectResult = await client.ConnectAsync(testEnvironment.ClientFactory.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();
var topicFilter = testEnvironment.ClientFactory.CreateTopicFilterBuilder().WithTopic("Topic").Build();
var subscribeOptions = testEnvironment.ClientFactory.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.PublishStringAsync("Topic", "Payload", retain: true);
await LongTestDelay();
@@ -54,31 +53,31 @@ namespace MQTTnet.Tests.Server
applicationMessageHandler.ReceivedEventArgs[0].ApplicationMessage.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();
var topicFilter = testEnvironment.ClientFactory.CreateTopicFilterBuilder().WithTopic("Topic/A").Build();
var subscribeOptions = testEnvironment.ClientFactory.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();
topicFilter = testEnvironment.ClientFactory.CreateTopicFilterBuilder().WithTopic("Topic/+").Build();
subscribeOptions = testEnvironment.ClientFactory.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.PublishStringAsync("Topic/A", "Payload", retain: true);
await LongTestDelay();
@@ -8,6 +8,7 @@ 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
+4 -7
View File
@@ -1,4 +1,3 @@
#if !WINDOWS_UWP && (NET48_OR_GREATER || NET5_0_OR_GREATER)
using System;
using System.Linq;
using System.Net;
@@ -9,7 +8,6 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Certificates;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Server;
using MQTTnet.Tests.Mockups;
@@ -25,7 +23,7 @@ namespace MQTTnet.Tests.Server
sanBuilder.AddIpAddress(IPAddress.Loopback);
sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);
sanBuilder.AddDnsName("localhost");
using (var rsa = RSA.Create())
{
var certRequest = new CertificateRequest("CN=localhost", rsa, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
@@ -53,7 +51,7 @@ namespace MQTTnet.Tests.Server
public async Task Tls_Swap_Test()
{
var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500);
var serverOptionsBuilder = testEnvironment.Factory.CreateServerOptionsBuilder();
var serverOptionsBuilder = testEnvironment.ServerFactory.CreateServerOptionsBuilder();
var firstOid = "1.3.6.1.5.5.7.3.1";
var secondOid = "1.3.6.1.5.5.7.3.2";
@@ -175,7 +173,7 @@ namespace MQTTnet.Tests.Server
static async Task<IMqttClient> ConnectClientAsync(TestEnvironment testEnvironment, Func<MqttClientCertificateValidationEventArgs, bool> certValidator)
{
var clientOptionsBuilder = testEnvironment.Factory.CreateClientOptionsBuilder();
var clientOptionsBuilder = testEnvironment.ClientFactory.CreateClientOptionsBuilder();
clientOptionsBuilder.WithClientId(Guid.NewGuid().ToString())
.WithTcpServer("localhost", 8883)
.WithTlsOptions(
@@ -187,7 +185,7 @@ namespace MQTTnet.Tests.Server
var clientOptions = clientOptionsBuilder.Build();
return await testEnvironment.ConnectClient(clientOptions);
}
sealed class CertificateProvider : ICertificateProvider
{
public X509Certificate2 CurrentCertificate { get; set; }
@@ -199,4 +197,3 @@ namespace MQTTnet.Tests.Server
}
}
}
#endif
@@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Internal;
@@ -21,18 +20,18 @@ namespace MQTTnet.Tests.Server
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()
{
@@ -49,7 +48,7 @@ namespace MQTTnet.Tests.Server
{
receivedTopics.Add(e.ApplicationMessage.Topic);
}
return CompletedTask.Instance;
};
@@ -5,7 +5,7 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Exceptions;
using MQTTnet.Formatter;
using MQTTnet.Internal;
using MQTTnet.Protocol;
@@ -49,7 +49,7 @@ namespace MQTTnet.Tests.Server
var client = await testEnvironment.ConnectClient();
var unsubscribeOptions = testEnvironment.Factory.CreateUnsubscribeOptionsBuilder().WithTopicFilter("X").WithUserProperty("A", "1").Build();
var unsubscribeOptions = testEnvironment.ClientFactory.CreateUnsubscribeOptionsBuilder().WithTopicFilter("X").WithUserProperty("A", "1").Build();
await client.UnsubscribeAsync(unsubscribeOptions);
CollectionAssert.AreEqual(unsubscribeOptions.UserProperties.ToList(), eventArgs.UserProperties);
@@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
using MQTTnet.Implementations;
using MQTTnet.Internal;
@@ -4,7 +4,6 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Formatter;
namespace MQTTnet.Tests.Server
@@ -20,14 +19,14 @@ namespace MQTTnet.Tests.Server
await testEnvironment.StartServer();
var client = testEnvironment.CreateClient();
var connectResult = await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
var connectResult = await client.ConnectAsync(testEnvironment.ClientFactory.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()
{
@@ -36,7 +35,7 @@ namespace MQTTnet.Tests.Server
await testEnvironment.StartServer();
var client = testEnvironment.CreateClient();
var connectResult = await client.ConnectAsync(testEnvironment.Factory.CreateClientOptionsBuilder()
var connectResult = await client.ConnectAsync(testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithProtocolVersion(MqttProtocolVersion.V500)
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
@@ -1,6 +1,5 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client;
using MQTTnet.Internal;
using MQTTnet.Protocol;
@@ -4,6 +4,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Server;
using MQTTnet.Server.Internal;
namespace MQTTnet.Tests
{