public async Task ManagedClients_Will_Message_Send() { using (var testEnvironment = new TestEnvironment(TestContext)) { var receivedMessagesCount = 0; await testEnvironment.StartServerAsync(); var willMessage = new MqttApplicationMessageBuilder().WithTopic("My/last/will").WithAtMostOnceQoS().Build(); var clientOptions = new MqttClientOptionsBuilder() .WithTcpServer("localhost", testEnvironment.ServerPort) .WithWillMessage(willMessage); var dyingClient = testEnvironment.CreateClient(); var dyingManagedClient = new ManagedMqttClient(dyingClient, testEnvironment.ClientLogger); await dyingManagedClient.StartAsync(new ManagedMqttClientOptionsBuilder() .WithClientOptions(clientOptions) .Build()); var recievingClient = await testEnvironment.ConnectClientAsync(); await recievingClient.SubscribeAsync("My/last/will"); recievingClient.UseApplicationMessageReceivedHandler(context => Interlocked.Increment(ref receivedMessagesCount)); dyingManagedClient.Dispose(); await Task.Delay(1000); Assert.AreEqual(1, receivedMessagesCount); } }
public async Task Start_Stop() { using (var testEnvironment = new TestEnvironment(TestContext)) { var server = await testEnvironment.StartServerAsync(); var managedClient = new ManagedMqttClient(testEnvironment.CreateClient(), new MqttNetLogger()); 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.GetClientStatusAsync()).Count); } }
public async Task Start_Stop() { using (var testEnvironment = new TestEnvironment()) { var factory = new MqttFactory(); var server = await testEnvironment.StartServerAsync(); var managedClient = new ManagedMqttClient(testEnvironment.CreateClient(), new MqttNetLogger().CreateChildLogger()); var clientOptions = new MqttClientOptionsBuilder() .WithTcpServer("localhost", testEnvironment.ServerPort); TaskCompletionSource <bool> connected = new TaskCompletionSource <bool>(); managedClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(e => { connected.SetResult(true); }); await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder() .WithClientOptions(clientOptions) .Build()); await connected.Task; await managedClient.StopAsync(); Assert.AreEqual(0, (await server.GetClientStatusAsync()).Count); } }
async Task <ManagedMqttClient> CreateManagedClientAsync( TestEnvironment testEnvironment, IMqttClient underlyingClient = null, TimeSpan?connectionCheckInterval = null) { await testEnvironment.StartServerAsync(); var clientOptions = new MqttClientOptionsBuilder() .WithTcpServer("localhost", testEnvironment.ServerPort); 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 ManagedMqttClient(underlyingClient ?? testEnvironment.CreateClient(), new MqttNetLogger()); var connected = GetConnectedTask(managedClient); await managedClient.StartAsync(managedOptions); await connected; return(managedClient); }
public async Task Storage_Queue_Drains() { using (var testEnvironment = new TestEnvironment()) { testEnvironment.IgnoreClientLogErrors = true; testEnvironment.IgnoreServerLogErrors = true; var factory = new MqttFactory(); var server = await testEnvironment.StartServerAsync(); var managedClient = new ManagedMqttClient(testEnvironment.CreateClient(), new MqttNetLogger().CreateChildLogger()); var clientOptions = new MqttClientOptionsBuilder() .WithTcpServer("localhost", testEnvironment.ServerPort); var storage = new ManagedMqttClientTestStorage(); TaskCompletionSource <bool> connected = new TaskCompletionSource <bool>(); managedClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(e => { managedClient.ConnectedHandler = null; connected.SetResult(true); }); await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder() .WithClientOptions(clientOptions) .WithStorage(storage) .WithAutoReconnectDelay(System.TimeSpan.FromSeconds(5)) .Build()); await connected.Task; await testEnvironment.Server.StopAsync(); await managedClient.PublishAsync(new MqttApplicationMessage { Topic = "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 = new TaskCompletionSource <bool>(); managedClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(e => { managedClient.ConnectedHandler = null; connected.SetResult(true); }); await testEnvironment.Server.StartAsync(new MqttServerOptionsBuilder() .WithDefaultEndpointPort(testEnvironment.ServerPort).Build()); await connected.Task; //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(); } }
public async Task Connect_With_AssignedClientId() { using (var testEnvironment = new TestEnvironment(TestContext)) { string serverConnectedClientId = null; string serverDisconnectedClientId = null; string clientAssignedClientId = null; // Arrange server var disconnectedMre = new ManualResetEventSlim(); var serverOptions = new MqttServerOptionsBuilder() .WithConnectionValidator((context) => { if (string.IsNullOrEmpty(context.ClientId)) { context.AssignedClientIdentifier = "test123"; context.ReasonCode = MqttConnectReasonCode.Success; } }); await testEnvironment.StartServerAsync(serverOptions); testEnvironment.Server.UseClientConnectedHandler((args) => { serverConnectedClientId = args.ClientId; }); testEnvironment.Server.UseClientDisconnectedHandler((args) => { serverDisconnectedClientId = args.ClientId; disconnectedMre.Set(); }); // Arrange client var client = testEnvironment.CreateClient(); client.UseConnectedHandler((args) => { clientAssignedClientId = args.AuthenticateResult.AssignedClientIdentifier; }); // Act await client.ConnectAsync(new MqttClientOptionsBuilder() .WithTcpServer("127.0.0.1", testEnvironment.ServerPort) .WithProtocolVersion(MqttProtocolVersion.V500) .WithClientId(null) .Build()); await client.DisconnectAsync(); // Wait for ClientDisconnectedHandler to trigger disconnectedMre.Wait(500); // Assert Assert.IsNotNull(serverConnectedClientId); Assert.IsNotNull(serverDisconnectedClientId); Assert.IsNotNull(clientAssignedClientId); Assert.AreEqual("test123", serverConnectedClientId); Assert.AreEqual("test123", serverDisconnectedClientId); Assert.AreEqual("test123", clientAssignedClientId); } }
public async Task Use_Clean_Session() { using (var testEnvironment = new TestEnvironment(TestContext)) { await testEnvironment.StartServerAsync(); var client = testEnvironment.CreateClient(); var connectResult = await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost", testEnvironment.ServerPort).WithCleanSession().Build()); Assert.IsFalse(connectResult.IsSessionPresent); } }
public async Task Clean_Session_Persistence() { using (var testEnvironment = new TestEnvironment(TestContext)) { // Create server with persistent sessions enabled await testEnvironment.StartServer(o => o.WithPersistentSessions()); const string ClientId = "Client1"; // Create client with clean session and long session expiry interval var client1 = await testEnvironment.ConnectClient(o => o .WithProtocolVersion(Formatter.MqttProtocolVersion.V311) .WithTcpServer("127.0.0.1", testEnvironment.ServerPort) .WithSessionExpiryInterval(9999) // not relevant for v311 but testing impact .WithCleanSession(true) // start and end with clean session .WithClientId(ClientId) .Build() ); // Disconnect; empty session should be removed from server await client1.DisconnectAsync(); // Simulate some time delay between connections await Task.Delay(1000); // Reconnect the same client ID without clean session var client2 = testEnvironment.CreateClient(); var options = testEnvironment.Factory.CreateClientOptionsBuilder() .WithProtocolVersion(Formatter.MqttProtocolVersion.V311) .WithTcpServer("127.0.0.1", testEnvironment.ServerPort) .WithSessionExpiryInterval(9999) // not relevant for v311 but testing impact .WithCleanSession(false) // see if there is a session .WithClientId(ClientId) .Build(); var result = await client2.ConnectAsync(options).ConfigureAwait(false); await client2.DisconnectAsync(); // Session should NOT be present for MQTT v311 and initial CleanSession == true Assert.IsTrue(!result.IsSessionPresent, "Session present"); } }
public async Task Validate_IsSessionPresent() { using (var testEnvironment = new TestEnvironment(TestContext)) { // Create server with persistent sessions enabled await testEnvironment.StartServer(o => o.WithPersistentSessions()); const string ClientId = "Client1"; // Create client without clean session and long session expiry interval var client1 = await testEnvironment.ConnectClient(o => o .WithProtocolVersion(MqttProtocolVersion.V500) .WithTcpServer("127.0.0.1", testEnvironment.ServerPort) .WithSessionExpiryInterval(9999) .WithCleanSession(false) .WithClientId(ClientId) .Build() ); // Disconnect; empty session should remain on server await client1.DisconnectAsync(); // Simulate some time delay between connections await Task.Delay(1000); // Reconnect the same client ID to existing session var client2 = testEnvironment.CreateClient(); var options = testEnvironment.Factory.CreateClientOptionsBuilder() .WithProtocolVersion(MqttProtocolVersion.V500) .WithTcpServer("127.0.0.1", testEnvironment.ServerPort) .WithSessionExpiryInterval(9999) .WithCleanSession(false) .WithClientId(ClientId) .Build(); var result = await client2.ConnectAsync(options).ConfigureAwait(false); await client2.DisconnectAsync(); // Session should be present Assert.IsTrue(result.IsSessionPresent, "Session not present"); } }
public async Task Use_Empty_Client_ID() { using (var testEnvironment = new TestEnvironment(TestContext)) { await testEnvironment.StartServerAsync(); var client = testEnvironment.CreateClient(); var clientOptions = new MqttClientOptionsBuilder() .WithTcpServer("localhost", testEnvironment.ServerPort) .WithClientId(string.Empty) .Build(); var connectResult = await client.ConnectAsync(clientOptions); Assert.IsFalse(connectResult.IsSessionPresent); Assert.IsTrue(client.IsConnected); } }
public async Task Use_Admissible_Credentials(string username, string password) { using (var testEnvironment = new TestEnvironment()) { await testEnvironment.StartServer(); var client = testEnvironment.CreateClient(); var clientOptions = new MqttClientOptionsBuilder() .WithTcpServer("localhost", testEnvironment.ServerPort) .WithCredentials(username, password) .Build(); var connectResult = await client.ConnectAsync(clientOptions); Assert.IsFalse(connectResult.IsSessionPresent); Assert.IsTrue(client.IsConnected); } }
public async Task Reconnect_From_Disconnected_Event() { using (var testEnvironment = new TestEnvironment(TestContext)) { testEnvironment.IgnoreClientLogErrors = true; var client = testEnvironment.CreateClient(); var tries = 0; var maxTries = 3; client.DisconnectedAsync += async e => { if (tries >= maxTries) { return; } Interlocked.Increment(ref tries); await Task.Delay(100); await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build()); }; try { await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build()); Assert.Fail("Must fail!"); } catch { } SpinWait.SpinUntil(() => tries >= maxTries, 10000); Assert.AreEqual(maxTries, tries); } }
public async Task Subscribe_In_Callback_Events() { using (var testEnvironment = new TestEnvironment(TestContext)) { await testEnvironment.StartServer(); var receivedMessages = new List <MqttApplicationMessage>(); var client = testEnvironment.CreateClient(); client.ConnectedAsync += async e => { await client.SubscribeAsync("RCU/P1/H0001/R0003"); var msg = new MqttApplicationMessageBuilder().WithPayload("DA|18RS00SC00XI0000RV00R100R200R300R400L100L200L300L400Y100Y200AC0102031800BELK0000BM0000|") .WithTopic("RCU/P1/H0001/R0003"); await client.PublishAsync(msg.Build()); }; client.ApplicationMessageReceivedAsync += e => { lock (receivedMessages) { receivedMessages.Add(e.ApplicationMessage); } return(PlatformAbstractionLayer.CompletedTask); }; await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost", testEnvironment.ServerPort).Build()); await Task.Delay(500); Assert.AreEqual(1, receivedMessages.Count); Assert.AreEqual("DA|18RS00SC00XI0000RV00R100R200R300R400L100L200L300L400Y100Y200AC0102031800BELK0000BM0000|", receivedMessages.First().ConvertPayloadToString()); } }
public async Task Subscriptions_Are_Cleared_At_Logout() { using (var testEnvironment = new TestEnvironment(TestContext)) { await testEnvironment.StartServerAsync().ConfigureAwait(false); var sendingClient = await testEnvironment.ConnectClientAsync().ConfigureAwait(false); await sendingClient.PublishAsync(new MqttApplicationMessage { Topic = "topic", Payload = new byte[] { 1 }, Retain = true }); // Wait a bit for the retained message to be available await Task.Delay(500); await sendingClient.DisconnectAsync(); // Now use the managed client and check if subscriptions get cleared properly. var clientOptions = new MqttClientOptionsBuilder() .WithTcpServer("localhost", testEnvironment.ServerPort); var receivedManagedMessages = new List <MqttApplicationMessage>(); var managedClient = new ManagedMqttClient(testEnvironment.CreateClient(), new MqttNetLogger()); managedClient.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(c => { receivedManagedMessages.Add(c.ApplicationMessage); }); await managedClient.SubscribeAsync("topic"); await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder() .WithClientOptions(clientOptions) .WithAutoReconnectDelay(TimeSpan.FromSeconds(1)) .Build()); await Task.Delay(500); Assert.AreEqual(1, receivedManagedMessages.Count); await managedClient.StopAsync(); await Task.Delay(500); await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder() .WithClientOptions(clientOptions) .WithAutoReconnectDelay(TimeSpan.FromSeconds(1)) .Build()); await Task.Delay(1000); // 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 Task.Delay(500); Assert.AreEqual(2, receivedManagedMessages.Count); } }
public async Task Subscriptions_And_Unsubscriptions_Are_Made_And_Reestablished_At_Reconnect() { using (var testEnvironment = new TestEnvironment(TestContext)) { 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.ConnectClientAsync(); async Task PublishMessages() { await sendingClient.PublishAsync("keptSubscribed", new byte[] { 1 }); await sendingClient.PublishAsync("subscribedThenUnsubscribed", new byte[] { 1 }); await sendingClient.PublishAsync("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(); } }