public async Task when_connect_clients_then_succeeds(int count) { List <IMqttClient> clients = new List <IMqttClient>(); List <string> clientIds = new List <string>(); List <Task> tasks = new List <Task>(); for (int i = 1; i <= count; i++) { IMqttClient client = await GetClientAsync(); string clientId = MqttTestHelper.GetClientId(); tasks.Add(client.ConnectAsync(new MqttClientCredentials(clientId))); clients.Add(client); clientIds.Add(clientId); } await Task.WhenAll(tasks); Server.ActiveClients.Where(c => clientIds.Contains(c)).Should().HaveCount(count); Assert.True(clients.All(c => c.IsConnected)); Assert.True(clients.All(c => !string.IsNullOrEmpty(c.Id))); foreach (IMqttClient client in clients) { client.Dispose(); } }
public async Task when_in_process_client_communicate_with_tcp_client_then_succeeds() { IMqttConnectedClient inProcessClient = await Server.CreateClientAsync(); IMqttClient remoteClient = await GetClientAsync(); await remoteClient.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId())); string fooTopic = "foo/message"; string barTopic = "bar/message"; await inProcessClient.SubscribeAsync(fooTopic, MqttQualityOfService.ExactlyOnce); await remoteClient.SubscribeAsync(barTopic, MqttQualityOfService.AtLeastOnce); int fooMessagesReceived = 0; int barMessagesReceived = 0; inProcessClient.MessageStream.Subscribe(message => { if (message.Topic == fooTopic) { fooMessagesReceived++; } }); remoteClient.MessageStream.Subscribe(message => { if (message.Topic == barTopic) { barMessagesReceived++; } }); await remoteClient.PublishAsync(new MqttApplicationMessage( fooTopic, new byte[255] ), MqttQualityOfService.AtMostOnce); await remoteClient.PublishAsync(new MqttApplicationMessage( fooTopic, new byte[10] ), MqttQualityOfService.AtLeastOnce); await remoteClient.PublishAsync(new MqttApplicationMessage( "other/topic", new byte[500] ), MqttQualityOfService.ExactlyOnce); await remoteClient.PublishAsync(new MqttApplicationMessage( fooTopic, new byte[50] ), MqttQualityOfService.ExactlyOnce); await inProcessClient.PublishAsync(new MqttApplicationMessage( barTopic, new byte[255] ), MqttQualityOfService.AtMostOnce); await inProcessClient.PublishAsync(new MqttApplicationMessage( barTopic, new byte[10] ), MqttQualityOfService.AtLeastOnce); await inProcessClient.PublishAsync(new MqttApplicationMessage( "other/topic", new byte[500] ), MqttQualityOfService.ExactlyOnce); await inProcessClient.PublishAsync(new MqttApplicationMessage( barTopic, new byte[50] ), MqttQualityOfService.ExactlyOnce); await Task.Delay(TimeSpan.FromMilliseconds(1000)); Assert.True(inProcessClient.IsConnected); Assert.True(remoteClient.IsConnected); fooMessagesReceived.Should().Be(3); barMessagesReceived.Should().Be(3); inProcessClient.Dispose(); remoteClient.Dispose(); }
public async Task when_client_connects_with_valid_credentials_and_authentication_is_supported_then_connection_succeeds() { string username = "******"; string password = "******"; IMqttClient client = await GetClientAsync(); await client.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId(), username, password )); Assert.True(client.IsConnected); Assert.False(string.IsNullOrEmpty(client.Id)); }
public async Task when_connecting_twice_with_same_client_without_disconnecting_then_fails() { IMqttClient client = await GetClientAsync(); string clientId = MqttTestHelper.GetClientId(); await client.ConnectAsync(new MqttClientCredentials( clientId )); AggregateException ex = Assert.Throws <AggregateException>(() => client.ConnectAsync(new MqttClientCredentials(clientId)).Wait()); Assert.NotNull(ex); Assert.NotNull(ex.InnerException); Assert.True(ex.InnerException is MqttClientException); }
public async Task when_keep_alive_enabled_and_client_is_disposed_then_server_refresh_active_client_list() { IMqttClient client = await GetClientAsync(); await client.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId())); string clientId = client.Id; bool existClientAfterConnect = Server.ActiveClients.Any(c => c == clientId); ManualResetEventSlim clientClosed = new ManualResetEventSlim(); IDisposable subscription = Observable.Create <bool>(observer => { System.Timers.Timer timer = new System.Timers.Timer(); timer.Interval = 200; timer.Elapsed += (sender, args) => { if (Server.ActiveClients.Any(c => c == clientId)) { observer.OnNext(false); } else { observer.OnNext(true); clientClosed.Set(); observer.OnCompleted(); } }; timer.Start(); return(() => { timer.Dispose(); }); }) .Subscribe( _ => { }, ex => { Console.WriteLine($"Error: {ex.Message}"); }); client.Dispose(); bool serverDetectedClientClosed = clientClosed.Wait(TimeSpan.FromSeconds(KeepAliveSecs * 2)); subscription.Dispose(); Assert.True(existClientAfterConnect); Assert.True(serverDetectedClientClosed); Assert.False(Server.ActiveClients.Any(c => c == clientId)); }
public async Task when_disconnect_client_then_server_decrease_active_client_list() { using (IMqttClient client = await GetClientAsync()) { await client.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId())); string clientId = client.Id; bool existClientAfterConnect = Server.ActiveClients.Any(c => c == clientId); await client.DisconnectAsync(); ManualResetEventSlim clientClosed = new ManualResetEventSlim(); IDisposable subscription = Observable.Create <bool>(observer => { System.Timers.Timer timer = new System.Timers.Timer(); timer.Interval = 200; timer.Elapsed += (sender, args) => { if (Server.ActiveClients.Any(c => c == clientId)) { observer.OnNext(false); } else { observer.OnNext(true); clientClosed.Set(); observer.OnCompleted(); } }; timer.Start(); return(() => { timer.Dispose(); }); }) .Subscribe( _ => { }, ex => { Console.WriteLine("Error: {0}", ex.Message); }); bool clientDisconnected = clientClosed.Wait(2000); Assert.True(existClientAfterConnect); Assert.True(clientDisconnected); Server.ActiveClients.Should().NotContain(c => c == clientId); } }
public async Task when_connecting_twice_with_same_client_with_disconnecting_then_succeeds() { using (IMqttClient client = await GetClientAsync()) { string clientId = MqttTestHelper.GetClientId(); await client.ConnectAsync(new MqttClientCredentials( clientId )); await client.DisconnectAsync(); await client.ConnectAsync(new MqttClientCredentials( clientId )); Server.ActiveClients.Count(c => c == clientId).Should().Be(1); } }
public async Task when_client_disconnects_by_protocol_then_will_message_is_not_sent() { using (IMqttClient client1 = await GetClientAsync()) using (IMqttClient client2 = await GetClientAsync()) using (IMqttClient client3 = await GetClientAsync()) { string topic = Guid.NewGuid().ToString(); MqttQualityOfService qos = MqttQualityOfService.ExactlyOnce; bool retain = true; FooWillMessage willMessage = new FooWillMessage { Message = "Client 1 has been disconnected unexpectedly" }; MqttLastWill will = new MqttLastWill(topic, qos, retain, willMessage.GetPayload()); await client1.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId()), will); await client2.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId())); await client3.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId())); await client2.SubscribeAsync(topic, MqttQualityOfService.AtMostOnce); await client3.SubscribeAsync(topic, MqttQualityOfService.AtLeastOnce); ManualResetEventSlim willReceivedSignal = new ManualResetEventSlim(initialState: false); client2.MessageStream.Subscribe(m => { if (m.Topic == topic) { willReceivedSignal.Set(); } }); client3.MessageStream.Subscribe(m => { if (m.Topic == topic) { willReceivedSignal.Set(); } }); await client1.DisconnectAsync(); bool willReceived = willReceivedSignal.Wait(2000); Assert.False(willReceived); } }
public async Task when_keep_alive_enabled_and_no_packets_are_sent_then_connection_is_maintained() { IMqttClient client = await GetClientAsync(); string clientId = MqttTestHelper.GetClientId(); await client.ConnectAsync(new MqttClientCredentials( clientId )); await Task.Delay(TimeSpan.FromSeconds(KeepAliveSecs * 5)); Assert.True(Server.ActiveClients.Any(c => c == clientId)); Assert.True(client.IsConnected); Assert.False(string.IsNullOrEmpty(client.Id)); client.Dispose(); }
public async Task when_connect_clients_and_one_client_drops_connection_then_other_client_survives() { using (IMqttClient fooClient = await GetClientAsync()) using (IMqttClient barClient = await GetClientAsync()) { string fooClientId = MqttTestHelper.GetClientId(); string barClientId = MqttTestHelper.GetClientId(); await fooClient.ConnectAsync(new MqttClientCredentials( fooClientId )); await barClient.ConnectAsync(new MqttClientCredentials( barClientId )); List <string> clientIds = new List <string> { fooClientId, barClientId }; int initialConnectedClients = Server.ActiveClients.Where(c => clientIds.Contains(c)).Count(); bool exceptionThrown = false; try { //Force an exception to be thrown by publishing null message await fooClient.PublishAsync(message : null, qos : MqttQualityOfService.AtMostOnce); } catch { exceptionThrown = true; } ManualResetEventSlim serverSignal = new ManualResetEventSlim(); while (!serverSignal.IsSet) { if (!Server.ActiveClients.Any(c => c == fooClientId)) { serverSignal.Set(); } } serverSignal.Wait(); int finalConnectedClients = Server.ActiveClients.Where(c => clientIds.Contains(c)).Count(); initialConnectedClients.Should().Be(2); Assert.True(exceptionThrown); finalConnectedClients.Should().Be(1); } }
public async Task when_client_disconnects_then_message_stream_completes() { ManualResetEventSlim streamCompletedSignal = new ManualResetEventSlim(initialState: false); IMqttClient client = await GetClientAsync(); await client.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId())); client.MessageStream.Subscribe(_ => { }, onCompleted: () => streamCompletedSignal.Set()); await client.DisconnectAsync(); bool streamCompleted = streamCompletedSignal.Wait(2000); Assert.True(streamCompleted); client.Dispose(); }
public async Task when_connecting_client_with_clean_session_false_then_session_is_preserved() { using (IMqttClient client = await GetClientAsync()) { string clientId = MqttTestHelper.GetClientId(); SessionState sessionState1 = await client.ConnectAsync(new MqttClientCredentials( clientId ), cleanSession : false); await client.DisconnectAsync(); SessionState sessionState2 = await client.ConnectAsync(new MqttClientCredentials( clientId ), cleanSession : false); await client.DisconnectAsync(); sessionState1.Should().Be(SessionState.CleanSession); sessionState2.Should().Be(SessionState.SessionPresent); } }
public async Task when_disconnect_clients_then_succeeds(int count) { List <IMqttClient> clients = new List <IMqttClient>(); List <string> clientIds = new List <string>(); for (int i = 1; i <= count; i++) { IMqttClient client = await GetClientAsync(); string clientId = MqttTestHelper.GetClientId(); await client.ConnectAsync(new MqttClientCredentials( clientId )); clients.Add(client); clientIds.Add(clientId); } int initialConnectedClients = Server.ActiveClients.Where(c => clientIds.Contains(c)).Count(); foreach (IMqttClient client in clients) { await client.DisconnectAsync(); } ManualResetEventSlim disconnectedSignal = new ManualResetEventSlim(initialState: false); while (!disconnectedSignal.IsSet) { if (Server.ActiveClients.Where(c => clientIds.Contains(c)).Count() == 0 && clients.All(c => !c.IsConnected)) { disconnectedSignal.Set(); } } initialConnectedClients.Should().Be(clients.Count); Server.ActiveClients.Where(c => clientIds.Contains(c)).Should().BeEmpty(); Assert.True(clients.All(c => !c.IsConnected)); Assert.True(clients.All(c => string.IsNullOrEmpty(c.Id))); foreach (IMqttClient client in clients) { client.Dispose(); } }
public async Task when_connecting_client_to_non_existing_server_then_fails() { try { Server.Dispose(); IMqttClient client = await GetClientAsync(); await client.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId())); } catch (Exception ex) { Assert.True(ex is MqttClientException); Assert.NotNull(ex.InnerException); //Assert.True( ex.InnerException is MqttException );//Not throwing this with SSL. //Assert.NotNull( ex.InnerException.InnerException ); //Assert.True( ex.InnerException.InnerException is SocketException ); } }
public async Task when_clients_connect_and_disconnect_then_server_raises_events() { using (IMqttClient fooClient = await GetClientAsync()) using (IMqttClient barClient = await GetClientAsync()) { string clientId1 = MqttTestHelper.GetClientId(); string clientId2 = MqttTestHelper.GetClientId(); List <string> connected = new List <string>(); List <string> disconnected = new List <string>(); Server.ClientConnected += (sender, id) => connected.Add(id); Server.ClientDisconnected += (sender, id) => { connected.Remove(id); disconnected.Add(id); }; await fooClient.ConnectAsync(new MqttClientCredentials( clientId1 )); connected.Should().BeEquivalentTo(clientId1); await barClient.ConnectAsync(new MqttClientCredentials( clientId2 )); connected.Should().BeEquivalentTo(clientId1, clientId2); await barClient.DisconnectAsync(); disconnected.Should().BeEquivalentTo(clientId2); connected.Should().BeEquivalentTo(clientId1); await fooClient.DisconnectAsync(); disconnected.Should().BeEquivalentTo(clientId2, clientId1); connected.Should().BeEmpty(); } }
public async Task when_client_disconnects_unexpectedly_then_will_message_is_sent() { IMqttClient client1 = await GetClientAsync(); IMqttClient client2 = await GetClientAsync(); IMqttClient client3 = await GetClientAsync(); string topic = Guid.NewGuid().ToString(); MqttQualityOfService qos = MqttQualityOfService.ExactlyOnce; bool retain = true; FooWillMessage willMessage = new FooWillMessage { Message = "Client 1 has been disconnected unexpectedly" }; byte[] willMessagePayload = willMessage.GetPayload(); MqttLastWill will = new MqttLastWill(topic, qos, retain, willMessagePayload); await client1.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId()), will); await client2.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId())); await client3.ConnectAsync(new MqttClientCredentials( MqttTestHelper.GetClientId())); await client2.SubscribeAsync(topic, MqttQualityOfService.AtMostOnce); await client3.SubscribeAsync(topic, MqttQualityOfService.AtLeastOnce); ManualResetEventSlim willReceivedSignal = new ManualResetEventSlim(initialState: false); MqttApplicationMessage willApplicationMessage = default; client2.MessageStream.Subscribe(m => { if (m.Topic == topic) { willApplicationMessage = m; willReceivedSignal.Set(); } }); client3.MessageStream.Subscribe(m => { if (m.Topic == topic) { willApplicationMessage = m; willReceivedSignal.Set(); } }); //Forces socket disconnection without using protocol Disconnect (Disconnect or Dispose Client method) (client1 as MqttClientImpl).Channel.Dispose(); bool willReceived = willReceivedSignal.Wait(2000); Assert.True(willReceived); Assert.NotNull(willMessage); willApplicationMessage.Topic.Should().Be(topic); FooWillMessage.GetMessage(willApplicationMessage.Payload).Message.Should().Be(willMessage.Message); client2.Dispose(); client3.Dispose(); }
public async Task when_client_connects_with_invalid_credentials_and_authentication_is_supported_then_connection_is_closed() { string username = "******"; string password = "******"; IMqttClient client = await GetClientAsync(); AggregateException aggregateEx = Assert.Throws <AggregateException>(() => client.ConnectAsync(new MqttClientCredentials(MqttTestHelper.GetClientId(), username, password)).Wait()); Assert.NotNull(aggregateEx.InnerException); Assert.True(aggregateEx.InnerException is MqttClientException); Assert.NotNull(aggregateEx.InnerException.InnerException); Assert.True(aggregateEx.InnerException.InnerException is MqttConnectionException); ((MqttConnectionException)aggregateEx.InnerException.InnerException).ReturnCode.Should().Be(MqttConnectionStatus.BadUserNameOrPassword); }
public async Task when_connecting_twice_from_two_client_with_same_id_server_first_client_disconnect_in_right_order() { string clientId = MqttTestHelper.GetClientId(); using (IMqttClient clientFoo = await GetClientAsync()) using (IMqttClient clientBar = await GetClientAsync()) { List <char> events = new List <char>(); void onConnect(object sender, string id) { lock ( events ) { events.Add('c'); Monitor.Pulse(events); } } void onDisconnect(object sender, string id) { lock ( events ) { events.Add('d'); Monitor.Pulse(events); } } Server.ClientDisconnected += onDisconnect; Server.ClientConnected += onConnect; await clientFoo.ConnectAsync(new MqttClientCredentials( clientId )); bool didNotTimeout = true; lock ( events ) { if (events.Count < 1) { didNotTimeout = Monitor.Wait(events, 500); } } Assert.True(didNotTimeout); string.Concat(events).Should().Be("c"); try { await clientBar.ConnectAsync(new MqttClientCredentials( clientId )); } catch { Assume.That(false, "To be investigated. Tests sometime throw exception on reconnection."); } lock ( events ) { while (events.Count < 4) { didNotTimeout &= Monitor.Wait(events, 500); } } Assert.True(didNotTimeout); string.Concat(events).Should().Be("ccdd"); Server.ClientDisconnected -= onDisconnect; Server.ClientConnected -= onConnect; //"cdc".Should().Be(events ); //Require MQTT-3.1.4-2 } }