Files
MQTTnet/Source/MQTTnet.Tests/Server/Retained_Messages_Tests.cs
T
980a5d0a6d 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>
2024-08-24 11:47:21 +02:00

271 lines
11 KiB
C#

// 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.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Formatter;
using MQTTnet.Packets;
using MQTTnet.Protocol;
namespace MQTTnet.Tests.Server
{
[TestClass]
public sealed class Retained_Messages_Tests : BaseTestClass
{
[TestMethod]
public async Task Clear_Retained_Message_With_Empty_Payload()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var c1 = await testEnvironment.ConnectClient();
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[0]).WithRetainFlag().Build());
await c1.DisconnectAsync();
var c2 = await testEnvironment.ConnectClient();
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
await Task.Delay(200);
await c2.SubscribeAsync(new MqttTopicFilter { Topic = "retained", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
await Task.Delay(500);
messageHandler.AssertReceivedCountEquals(0);
}
}
[TestMethod]
public async Task Clear_Retained_Message_With_Null_Payload()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var c1 = await testEnvironment.ConnectClient();
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload((byte[])null).WithRetainFlag().Build());
await c1.DisconnectAsync();
var c2 = await testEnvironment.ConnectClient();
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
await Task.Delay(200);
await c2.SubscribeAsync(new MqttTopicFilter { Topic = "retained", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
await Task.Delay(500);
messageHandler.AssertReceivedCountEquals(0);
}
}
[TestMethod]
public async Task Downgrade_QoS_Level()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var c1 = await testEnvironment.ConnectClient();
// Add the retained message with QoS 2!
await c1.PublishAsync(
new MqttApplicationMessageBuilder().WithTopic("retained")
.WithPayload(new byte[3])
.WithRetainFlag()
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.ExactlyOnce)
.Build());
// The second client uses QoS 1 so a downgrade is required.
var c2 = await testEnvironment.ConnectClient();
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
await c2.SubscribeAsync(new MqttTopicFilter { Topic = "retained", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
await LongTestDelay();
messageHandler.AssertReceivedCountEquals(1);
Assert.AreEqual(MqttQualityOfServiceLevel.AtLeastOnce, messageHandler.ReceivedEventArgs.First().ApplicationMessage.QualityOfServiceLevel);
}
}
[TestMethod]
public async Task No_Upgrade_QoS_Level()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var c1 = await testEnvironment.ConnectClient();
// Add the retained message with QoS 1!
await c1.PublishAsync(
new MqttApplicationMessageBuilder().WithTopic("retained")
.WithPayload(new byte[3])
.WithRetainFlag()
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
.Build());
// The second client uses QoS 2 so an upgrade is expected but according to the MQTT spec this is not supported!
var c2 = await testEnvironment.ConnectClient();
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
await c2.SubscribeAsync(new MqttTopicFilter { Topic = "retained", QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce });
await LongTestDelay();
messageHandler.AssertReceivedCountEquals(1);
Assert.AreEqual(MqttQualityOfServiceLevel.AtLeastOnce, messageHandler.ReceivedEventArgs.First().ApplicationMessage.QualityOfServiceLevel);
}
}
[TestMethod]
public async Task Receive_No_Retained_Message_After_Subscribe()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var c1 = await testEnvironment.ConnectClient();
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
await c1.DisconnectAsync();
var c2 = await testEnvironment.ConnectClient();
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
await c2.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("retained_other").Build());
await Task.Delay(500);
messageHandler.AssertReceivedCountEquals(0);
}
}
[TestMethod]
public async Task Receive_Retained_Message_After_Subscribe()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var c1 = await testEnvironment.ConnectClient();
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
await c1.DisconnectAsync();
var c2 = await testEnvironment.ConnectClient();
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
await c2.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("retained").Build());
await Task.Delay(500);
messageHandler.AssertReceivedCountEquals(1);
Assert.IsTrue(messageHandler.ReceivedEventArgs.First().ApplicationMessage.Retain);
}
}
[TestMethod]
public async Task Receive_Retained_Messages_From_Higher_Qos_Level()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
// Upload retained message.
var c1 = await testEnvironment.ConnectClient();
await c1.PublishAsync(
new MqttApplicationMessageBuilder().WithTopic("retained")
.WithPayload(new byte[1])
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
.WithRetainFlag()
.Build());
await c1.DisconnectAsync();
// Subscribe using a new client.
var c2 = await testEnvironment.ConnectClient();
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
await Task.Delay(200);
// Using QoS 2 will lead to 1 instead because the publish was made with QoS level 1 (see 3.8.4 SUBSCRIBE Actions)!
await c2.SubscribeAsync(new MqttTopicFilter { Topic = "retained", QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce });
await Task.Delay(500);
messageHandler.AssertReceivedCountEquals(1);
}
}
[TestMethod]
public async Task Retained_Messages_Flow()
{
using (var testEnvironment = CreateTestEnvironment())
{
var retainedMessage = new MqttApplicationMessageBuilder().WithTopic("r").WithPayload("r").WithRetainFlag().Build();
await testEnvironment.StartServer();
var c1 = await testEnvironment.ConnectClient();
var c2 = await testEnvironment.ConnectClient();
var messageHandler = testEnvironment.CreateApplicationMessageHandler(c2);
await c1.PublishAsync(retainedMessage);
await c1.DisconnectAsync();
await LongTestDelay();
for (var i = 0; i < 5; i++)
{
await c2.UnsubscribeAsync("r");
await Task.Delay(100);
messageHandler.AssertReceivedCountEquals(i);
await c2.SubscribeAsync("r");
await Task.Delay(100);
messageHandler.AssertReceivedCountEquals(i + 1);
}
await c2.DisconnectAsync();
}
}
[TestMethod]
public async Task Server_Reports_Retained_Messages_Supported_V3()
{
using (var testEnvironment = CreateTestEnvironment())
{
await testEnvironment.StartServer();
var client = testEnvironment.CreateClient();
var connectResult = await client.ConnectAsync(
testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithProtocolVersion(MqttProtocolVersion.V311)
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.Build());
Assert.IsTrue(connectResult.RetainAvailable);
}
}
[TestMethod]
public async Task Server_Reports_Retained_Messages_Supported_V5()
{
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
{
await testEnvironment.StartServer();
var client = testEnvironment.CreateClient();
var connectResult = await client.ConnectAsync(
testEnvironment.ClientFactory.CreateClientOptionsBuilder()
.WithProtocolVersion(MqttProtocolVersion.V500)
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
.Build());
Assert.IsTrue(connectResult.RetainAvailable);
}
}
}
}