diff --git a/Build/MQTTnet.nuspec b/Build/MQTTnet.nuspec
index fc5d2bd9..5112cd5c 100644
--- a/Build/MQTTnet.nuspec
+++ b/Build/MQTTnet.nuspec
@@ -19,6 +19,7 @@
* [Core] Mono is now also supported (Thanks to JTrotta)
* [Client] The options are now passed in _ConnectAsync_ (Breaking change!)
* [Core] Trace class renamed to _MqttNetTrace_ (Breaking change!)
+* [Client] Extended certificate validation options (Breaking change!)
Copyright Christian Kratky 2016-2017
MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M
diff --git a/README.md b/README.md
index c3993a10..8b7594d8 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ MQTTnet is a .NET library for MQTT based communication. It provides a MQTT clien
* Performance optimized (processing ~27.000 messages / second)*
* Interfaces included for mocking and testing
* Access to internal trace messages
-* Unit tested (58+ tests)
+* Unit tested (62+ tests)
\* Tested on local machine with MQTTnet client and server running in the same process using the TCP channel. The app for verification is part of this repository and stored in _/Tests/MQTTnet.TestApp.NetFramework_.
diff --git a/Tests/MQTTnet.Core.Tests/MqttServerTests.cs b/Tests/MQTTnet.Core.Tests/MqttServerTests.cs
index f198576c..26a48e57 100644
--- a/Tests/MQTTnet.Core.Tests/MqttServerTests.cs
+++ b/Tests/MQTTnet.Core.Tests/MqttServerTests.cs
@@ -81,7 +81,7 @@ namespace MQTTnet.Core.Tests
var receivedMessagesCount = 0;
c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
-
+
var message = new MqttApplicationMessage("a", new byte[0], MqttQualityOfServiceLevel.AtLeastOnce, false);
await c2.PublishAsync(message);
@@ -126,9 +126,124 @@ namespace MQTTnet.Core.Tests
await s.StopAsync();
Assert.AreEqual(1, receivedMessagesCount);
- }
+ }
- private async Task TestPublishAsync(
+ [TestMethod]
+ public async Task MqttServer_NoRetainedMessage()
+ {
+ var serverAdapter = new TestMqttServerAdapter();
+ var s = new MqttServer(new MqttServerOptions(), new List { serverAdapter });
+ await s.StartAsync();
+
+ var c1 = await serverAdapter.ConnectTestClient(s, "c1");
+ await c1.PublishAsync(new MqttApplicationMessage("retained", new byte[3], MqttQualityOfServiceLevel.AtLeastOnce, false));
+ await c1.DisconnectAsync();
+
+ var c2 = await serverAdapter.ConnectTestClient(s, "c2");
+ var receivedMessagesCount = 0;
+ c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
+ await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtLeastOnce));
+
+ await Task.Delay(500);
+
+ await s.StopAsync();
+
+ Assert.AreEqual(0, receivedMessagesCount);
+ }
+
+ [TestMethod]
+ public async Task MqttServer_RetainedMessage()
+ {
+ var serverAdapter = new TestMqttServerAdapter();
+ var s = new MqttServer(new MqttServerOptions(), new List { serverAdapter });
+ await s.StartAsync();
+
+ var c1 = await serverAdapter.ConnectTestClient(s, "c1");
+ await c1.PublishAsync(new MqttApplicationMessage("retained", new byte[3], MqttQualityOfServiceLevel.AtLeastOnce, true));
+ await c1.DisconnectAsync();
+
+ var c2 = await serverAdapter.ConnectTestClient(s, "c2");
+ var receivedMessagesCount = 0;
+ c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
+ await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtLeastOnce));
+
+ await Task.Delay(500);
+
+ await s.StopAsync();
+
+ Assert.AreEqual(1, receivedMessagesCount);
+ }
+
+ [TestMethod]
+ public async Task MqttServer_ClearRetainedMessage()
+ {
+ var serverAdapter = new TestMqttServerAdapter();
+ var s = new MqttServer(new MqttServerOptions(), new List { serverAdapter });
+ await s.StartAsync();
+
+ var c1 = await serverAdapter.ConnectTestClient(s, "c1");
+ await c1.PublishAsync(new MqttApplicationMessage("retained", new byte[3], MqttQualityOfServiceLevel.AtLeastOnce, true));
+ await c1.DisconnectAsync();
+
+ var c2 = await serverAdapter.ConnectTestClient(s, "c2");
+ var receivedMessagesCount = 0;
+ c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
+ await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtLeastOnce));
+
+ await Task.Delay(500);
+
+ await s.StopAsync();
+
+ Assert.AreEqual(1, receivedMessagesCount);
+ }
+
+ [TestMethod]
+ public async Task MqttServer_PersistRetainedMessage()
+ {
+ var storage = new TestStorage();
+
+ var serverAdapter = new TestMqttServerAdapter();
+ var s = new MqttServer(new MqttServerOptions { Storage = storage }, new List { serverAdapter });
+ await s.StartAsync();
+
+ var c1 = await serverAdapter.ConnectTestClient(s, "c1");
+ await c1.PublishAsync(new MqttApplicationMessage("retained", new byte[3], MqttQualityOfServiceLevel.AtLeastOnce, true));
+ await c1.DisconnectAsync();
+
+ await s.StopAsync();
+
+ s = new MqttServer(new MqttServerOptions { Storage = storage }, new List { serverAdapter });
+ await s.StartAsync();
+
+ var c2 = await serverAdapter.ConnectTestClient(s, "c2");
+ var receivedMessagesCount = 0;
+ c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
+ await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtLeastOnce));
+
+ await Task.Delay(500);
+
+ await s.StopAsync();
+
+ Assert.AreEqual(1, receivedMessagesCount);
+ }
+
+ private class TestStorage : IMqttServerStorage
+ {
+ private IList _messages = new List();
+
+ public Task SaveRetainedMessagesAsync(IList messages)
+ {
+ _messages = messages;
+ return Task.FromResult(0);
+ }
+
+ public Task> LoadRetainedMessagesAsync()
+ {
+ return Task.FromResult(_messages);
+ }
+ }
+
+ private static async Task TestPublishAsync(
string topic,
MqttQualityOfServiceLevel qualityOfServiceLevel,
string topicFilter,