From be0c75439c90a650f695665eaa30aca14a26a33f Mon Sep 17 00:00:00 2001 From: Christian <6939810+chkr1011@users.noreply.github.com> Date: Sat, 29 Jul 2023 09:48:07 +0200 Subject: [PATCH] Add Unit Tests --- .../MQTTnet.Extensions.Rpc/MqttRpcClient.cs | 5 ++ .../MqttClient/MqttClient_Connection_Tests.cs | 45 ++++++++++++++ .../MqttClient/MqttClient_Publish_Tests.cs | 59 +++++++++++++++++++ .../Clients/MqttClient/MqttClient_Tests.cs | 32 +--------- .../Clients/MqttClientOptionsBuilder_Tests.cs | 2 +- Source/MQTTnet/Client/MqttClient.cs | 1 + ...MqttApplicationMessageReceivedEventArgs.cs | 2 +- Source/MQTTnet/Server/MqttServer.cs | 6 ++ Source/MQTTnet/Server/MqttServerExtensions.cs | 28 ++++++++- 9 files changed, 146 insertions(+), 34 deletions(-) create mode 100644 Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Publish_Tests.cs diff --git a/Source/MQTTnet.Extensions.Rpc/MqttRpcClient.cs b/Source/MQTTnet.Extensions.Rpc/MqttRpcClient.cs index aab296c9..a279cae0 100644 --- a/Source/MQTTnet.Extensions.Rpc/MqttRpcClient.cs +++ b/Source/MQTTnet.Extensions.Rpc/MqttRpcClient.cs @@ -69,6 +69,11 @@ namespace MQTTnet.Extensions.Rpc throw new ArgumentNullException(nameof(methodName)); } + if (!_mqttClient.IsConnected) + { + throw new MqttClientDisconnectedException(null); + } + var context = new TopicGenerationContext(_mqttClient, _options, methodName, qualityOfServiceLevel); var topicNames = _options.TopicGenerationStrategy.CreateRpcTopics(context); diff --git a/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Connection_Tests.cs b/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Connection_Tests.cs index d38fc692..04674e54 100644 --- a/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Connection_Tests.cs +++ b/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Connection_Tests.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using MQTTnet.Client; using MQTTnet.Exceptions; +using MQTTnet.Extensions.Rpc; using MQTTnet.Formatter; using MQTTnet.Internal; using MQTTnet.Packets; @@ -20,6 +21,38 @@ namespace MQTTnet.Tests.Clients.MqttClient [TestClass] public sealed class MqttClient_Connection_Tests : BaseTestClass { + [TestMethod] + public async Task Connect_Disconnect_Connect() + { + using (var testEnvironment = CreateTestEnvironment()) + { + await testEnvironment.StartServer(); + + var clientOptions = testEnvironment.CreateDefaultClientOptions(); + var client = testEnvironment.CreateClient(); + + await client.ConnectAsync(clientOptions); + await client.DisconnectAsync(); + await client.ConnectAsync(clientOptions); + } + } + + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public async Task Connect_Multiple_Times_Should_Fail() + { + using (var testEnvironment = CreateTestEnvironment()) + { + await testEnvironment.StartServer(); + + var clientOptions = testEnvironment.CreateDefaultClientOptions(); + var client = testEnvironment.CreateClient(); + + await client.ConnectAsync(clientOptions); + await client.ConnectAsync(clientOptions); + } + } + [TestMethod] [ExpectedException(typeof(MqttCommunicationException))] public async Task Connect_To_Invalid_Server_Port_Not_Opened() @@ -196,5 +229,17 @@ namespace MQTTnet.Tests.Clients.MqttClient Assert.AreEqual(response.UserProperties[0].Value, "Value"); } } + + [TestMethod] + [ExpectedException(typeof(MqttClientDisconnectedException))] + public async Task Rpc_Client_Not_Connected() + { + var factory = new MqttFactory(); + using (var client = factory.CreateMqttClient()) + { + var rpcClient = factory.CreateMqttRpcClient(client); + await rpcClient.ExecuteAsync("aaa", new byte[] { 1, 2, 3 }, MqttQualityOfServiceLevel.AtLeastOnce); + } + } } } \ No newline at end of file diff --git a/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Publish_Tests.cs b/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Publish_Tests.cs new file mode 100644 index 00000000..f94ed96f --- /dev/null +++ b/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Publish_Tests.cs @@ -0,0 +1,59 @@ +// 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; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using MQTTnet.Client; +using MQTTnet.Protocol; +using MQTTnet.Server; + +namespace MQTTnet.Tests.Clients.MqttClient +{ + [TestClass] + public sealed class MqttClient_Publish_Tests : BaseTestClass + { + [TestMethod] + public async Task Acknowledge_After_Disconnect_Should_Fail() + { + using (var testEnvironment = CreateTestEnvironment()) + { + var server = await testEnvironment.StartServer(); + + var client = await testEnvironment.ConnectClient(); + await client.SubscribeAsync("TEST", MqttQualityOfServiceLevel.AtLeastOnce); + + var flag = false; + + client.ApplicationMessageReceivedAsync += async args => + { + try + { + args.AutoAcknowledge = false; + + await client.DisconnectAsync(); + await args.AcknowledgeAsync(); + + flag = true; + } + catch (Exception exception) + { + + } + }; + + await server.InjectApplicationMessageAsync( + new MqttApplicationMessage + { + Topic = "TEST" + }); + + SpinWait.SpinUntil(() => flag, TimeSpan.FromSeconds(10)); + + Assert.IsTrue(flag); + } + } + } +} \ No newline at end of file diff --git a/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Tests.cs b/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Tests.cs index 7b65e07f..a09c90c9 100644 --- a/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Tests.cs +++ b/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Tests.cs @@ -69,38 +69,8 @@ namespace MQTTnet.Tests.Clients.MqttClient Assert.IsTrue(success); } } + - [TestMethod] - public async Task Connect_Disconnect_Connect() - { - using (var testEnvironment = CreateTestEnvironment()) - { - await testEnvironment.StartServer(); - - var clientOptions = testEnvironment.CreateDefaultClientOptions(); - var client = testEnvironment.CreateClient(); - - await client.ConnectAsync(clientOptions); - await client.DisconnectAsync(); - await client.ConnectAsync(clientOptions); - } - } - - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public async Task Connect_Multiple_Times_Should_Fail() - { - using (var testEnvironment = CreateTestEnvironment()) - { - await testEnvironment.StartServer(); - - var clientOptions = testEnvironment.CreateDefaultClientOptions(); - var client = testEnvironment.CreateClient(); - - await client.ConnectAsync(clientOptions); - await client.ConnectAsync(clientOptions); - } - } [TestMethod] public async Task Disconnect_Event_Contains_Exception() diff --git a/Source/MQTTnet.Tests/Clients/MqttClientOptionsBuilder_Tests.cs b/Source/MQTTnet.Tests/Clients/MqttClientOptionsBuilder_Tests.cs index dac2404e..a57df305 100644 --- a/Source/MQTTnet.Tests/Clients/MqttClientOptionsBuilder_Tests.cs +++ b/Source/MQTTnet.Tests/Clients/MqttClientOptionsBuilder_Tests.cs @@ -10,7 +10,7 @@ using MQTTnet.Client; namespace MQTTnet.Tests.Clients { [TestClass] - public class MqttClientOptionsBuilder_Tests + public sealed class MqttClientOptionsBuilder_Tests { [TestMethod] public void WithConnectionUri_Credential_Test() diff --git a/Source/MQTTnet/Client/MqttClient.cs b/Source/MQTTnet/Client/MqttClient.cs index 2b851ea6..68931a13 100644 --- a/Source/MQTTnet/Client/MqttClient.cs +++ b/Source/MQTTnet/Client/MqttClient.cs @@ -881,6 +881,7 @@ namespace MQTTnet.Client _lastPacketSentTimestamp = DateTime.UtcNow; + //ThrowIfNotConnected(); return _adapter.SendPacketAsync(packet, cancellationToken); } diff --git a/Source/MQTTnet/Client/Receiving/MqttApplicationMessageReceivedEventArgs.cs b/Source/MQTTnet/Client/Receiving/MqttApplicationMessageReceivedEventArgs.cs index 3a699197..1c7b4a56 100644 --- a/Source/MQTTnet/Client/Receiving/MqttApplicationMessageReceivedEventArgs.cs +++ b/Source/MQTTnet/Client/Receiving/MqttApplicationMessageReceivedEventArgs.cs @@ -77,7 +77,7 @@ namespace MQTTnet.Client internal MqttPublishPacket PublishPacket { get; set; } - public Task AcknowledgeAsync(CancellationToken cancellationToken) + public Task AcknowledgeAsync(CancellationToken cancellationToken = default) { if (_acknowledgeHandler == null) { diff --git a/Source/MQTTnet/Server/MqttServer.cs b/Source/MQTTnet/Server/MqttServer.cs index ff6c806e..b505bd12 100644 --- a/Source/MQTTnet/Server/MqttServer.cs +++ b/Source/MQTTnet/Server/MqttServer.cs @@ -229,7 +229,13 @@ namespace MQTTnet.Server return _clientSessionsManager.GetSessionsStatus(); } + [Obsolete("Use InjectApplicationMessageAsync instead.")] public Task InjectApplicationMessage(InjectedMqttApplicationMessage injectedApplicationMessage, CancellationToken cancellationToken = default) + { + return InjectApplicationMessageAsync(injectedApplicationMessage, cancellationToken); + } + + public Task InjectApplicationMessageAsync(InjectedMqttApplicationMessage injectedApplicationMessage, CancellationToken cancellationToken = default) { if (injectedApplicationMessage == null) { diff --git a/Source/MQTTnet/Server/MqttServerExtensions.cs b/Source/MQTTnet/Server/MqttServerExtensions.cs index 72cdac24..540b4b95 100644 --- a/Source/MQTTnet/Server/MqttServerExtensions.cs +++ b/Source/MQTTnet/Server/MqttServerExtensions.cs @@ -13,12 +13,38 @@ namespace MQTTnet.Server { public static class MqttServerExtensions { + [Obsolete("Use InjectApplicationMessageAsync instead.")] public static Task InjectApplicationMessage( this MqttServer server, string topic, string payload = null, MqttQualityOfServiceLevel qualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce, bool retain = false) + { + return InjectApplicationMessageAsync(server, topic, payload, qualityOfServiceLevel, retain); + } + + public static Task InjectApplicationMessageAsync(this MqttServer server, MqttApplicationMessage applicationMessage) + { + if (server == null) + { + throw new ArgumentNullException(nameof(server)); + } + + if (applicationMessage == null) + { + throw new ArgumentNullException(nameof(applicationMessage)); + } + + return server.InjectApplicationMessageAsync(new InjectedMqttApplicationMessage(applicationMessage)); + } + + public static Task InjectApplicationMessageAsync( + this MqttServer server, + string topic, + string payload = null, + MqttQualityOfServiceLevel qualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce, + bool retain = false) { if (server == null) { @@ -36,7 +62,7 @@ namespace MQTTnet.Server payloadBuffer = Encoding.UTF8.GetBytes(stringPayload); } - return server.InjectApplicationMessage( + return server.InjectApplicationMessageAsync( new InjectedMqttApplicationMessage( new MqttApplicationMessage {